diff options
170 files changed, 2881 insertions, 1363 deletions
diff --git a/Android.bp b/Android.bp index 05fb3c083937..e65ba0f6a95f 100644 --- a/Android.bp +++ b/Android.bp @@ -249,8 +249,7 @@ java_library { "core/java/android/os/storage/IStorageEventListener.aidl", "core/java/android/os/storage/IStorageShutdownObserver.aidl", "core/java/android/os/storage/IObbActionListener.aidl", - "core/java/android/security/IConfirmationPromptCallback.aidl", - "core/java/android/security/IKeystoreService.aidl", + ":keystore_aidl", "core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl", "core/java/android/service/autofill/IAutoFillService.aidl", "core/java/android/service/autofill/IAutofillFieldClassificationService.aidl", @@ -425,6 +424,7 @@ java_library { "media/java/android/media/IAudioFocusDispatcher.aidl", "media/java/android/media/IAudioRoutesObserver.aidl", "media/java/android/media/IAudioService.aidl", + "media/java/android/media/IAudioServerStateDispatcher.aidl", "media/java/android/media/IMediaHTTPConnection.aidl", "media/java/android/media/IMediaHTTPService.aidl", "media/java/android/media/IMediaResourceMonitor.aidl", @@ -642,6 +642,7 @@ java_library { "system/netd/server/binder", "system/vold/binder", "system/bt/binder", + "system/security/keystore/binder", ], }, diff --git a/Android.mk b/Android.mk index f4208207e146..3b8d6a8ae8e5 100644 --- a/Android.mk +++ b/Android.mk @@ -804,7 +804,7 @@ LOCAL_PROTOC_FLAGS := \ -Iexternal/protobuf/src LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \ store_unknown_fields = true -LOCAL_JAVA_LIBRARIES := core-oj core-libart +LOCAL_SDK_VERSION := current LOCAL_SRC_FILES := \ $(call all-proto-files-under, core/proto) \ $(call all-proto-files-under, libs/incident/proto/android/os) diff --git a/api/current.txt b/api/current.txt index 3edd2c08bcf3..042360e6ff1b 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3695,7 +3695,7 @@ package android.app { method public boolean onCreateOptionsMenu(android.view.Menu); method public boolean onCreatePanelMenu(int, android.view.Menu); method public android.view.View onCreatePanelView(int); - method public boolean onCreateThumbnail(android.graphics.Bitmap, android.graphics.Canvas); + method public deprecated boolean onCreateThumbnail(android.graphics.Bitmap, android.graphics.Canvas); method public android.view.View onCreateView(java.lang.String, android.content.Context, android.util.AttributeSet); method public android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet); method protected void onDestroy(); @@ -6740,6 +6740,7 @@ package android.app.admin { field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455 field public static final int TAG_CERT_AUTHORITY_INSTALLED = 210029; // 0x3346d field public static final int TAG_CERT_AUTHORITY_REMOVED = 210030; // 0x3346e + field public static final int TAG_CERT_VALIDATION_FAILURE = 210033; // 0x33471 field public static final int TAG_CRYPTO_SELF_TEST_COMPLETED = 210031; // 0x3346f field public static final int TAG_KEYGUARD_DISABLED_FEATURES_SET = 210021; // 0x33465 field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456 @@ -6748,6 +6749,7 @@ package android.app.admin { field public static final int TAG_KEY_DESTRUCTION = 210026; // 0x3346a field public static final int TAG_KEY_GENERATED = 210024; // 0x33468 field public static final int TAG_KEY_IMPORT = 210025; // 0x33469 + field public static final int TAG_KEY_INTEGRITY_VIOLATION = 210032; // 0x33470 field public static final int TAG_LOGGING_STARTED = 210011; // 0x3345b field public static final int TAG_LOGGING_STOPPED = 210012; // 0x3345c field public static final int TAG_LOG_BUFFER_SIZE_CRITICAL = 210015; // 0x3345f @@ -40731,8 +40733,8 @@ package android.telecom { method public final void setActive(); method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>); method public final void setConnectionCapabilities(int); - method public final void setConnectionElapsedTime(long); method public final void setConnectionProperties(int); + method public final void setConnectionStartElapsedRealTime(long); method public final void setConnectionTime(long); method public final void setDialing(); method public final void setDisconnected(android.telecom.DisconnectCause); diff --git a/api/system-current.txt b/api/system-current.txt index 953941feb503..39cbe90894ee 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -437,6 +437,19 @@ package android.app.admin { field public static final int STATE_USER_UNMANAGED = 0; // 0x0 } + public class SystemUpdatePolicy implements android.os.Parcelable { + method public int describeContents(); + method public android.app.admin.SystemUpdatePolicy.InstallationOption getInstallationOptionAt(long); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.admin.SystemUpdatePolicy> CREATOR; + field public static final int TYPE_PAUSE = 4; // 0x4 + } + + public static class SystemUpdatePolicy.InstallationOption { + method public long getEffectiveTime(); + method public int getType(); + } + } package android.app.backup { @@ -2524,12 +2537,15 @@ package android.media { public class AudioManager { method public deprecated int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes); + method public void clearAudioServerStateCallback(); method public int dispatchAudioFocusChange(android.media.AudioFocusInfo, int, android.media.audiopolicy.AudioPolicy); + method public boolean isAudioServerRunning(); method public boolean isHdmiSystemAudioSupported(); method public int registerAudioPolicy(android.media.audiopolicy.AudioPolicy); method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException; method public deprecated int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException; method public int requestAudioFocus(android.media.AudioFocusRequest, android.media.audiopolicy.AudioPolicy); + method public void setAudioServerStateCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioServerStateCallback); method public void setFocusRequestResult(android.media.AudioFocusInfo, int, android.media.audiopolicy.AudioPolicy); method public void unregisterAudioPolicyAsync(android.media.audiopolicy.AudioPolicy); field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1 @@ -2537,6 +2553,12 @@ package android.media { field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2 } + public static abstract class AudioManager.AudioServerStateCallback { + ctor public AudioManager.AudioServerStateCallback(); + method public void onAudioServerDown(); + method public void onAudioServerUp(); + } + public final class AudioPlaybackConfiguration implements android.os.Parcelable { method public int getClientPid(); method public int getClientUid(); diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 3a20b12500ae..afb2c4782fac 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -21,6 +21,7 @@ #include <android-base/file.h> #include <dirent.h> #include "StatsLogProcessor.h" +#include "stats_log_util.h" #include "android-base/stringprintf.h" #include "guardrail/StatsdStats.h" #include "metrics/CountMetricProducer.h" @@ -59,8 +60,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; +const int FIELD_ID_LAST_REPORT_ELAPSED_NANOS = 3; +const int FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS = 4; #define STATS_DATA_DIR "/data/misc/stats-data" @@ -136,7 +137,7 @@ void StatsLogProcessor::onIsolatedUidChangedEventLocked(const LogEvent& event) { void StatsLogProcessor::OnLogEvent(LogEvent* event) { std::lock_guard<std::mutex> lock(mMetricsMutex); StatsdStats::getInstance().noteAtomLogged( - event->GetTagId(), event->GetTimestampNs() / NS_PER_SEC); + event->GetTagId(), event->GetElapsedTimestampNs() / NS_PER_SEC); // Hard-coded logic to update the isolated uid's in the uid-map. // The field numbers need to be currently updated by hand with atoms.proto @@ -148,10 +149,10 @@ void StatsLogProcessor::OnLogEvent(LogEvent* event) { return; } - long curTime = time(nullptr); - if (curTime - mLastPullerCacheClearTimeSec > StatsdStats::kPullerCacheClearIntervalSec) { - mStatsPullerManager.ClearPullerCacheIfNecessary(curTime); - mLastPullerCacheClearTimeSec = curTime; + uint64_t curTimeSec = getElapsedRealtimeSec(); + if (curTimeSec - mLastPullerCacheClearTimeSec > StatsdStats::kPullerCacheClearIntervalSec) { + mStatsPullerManager.ClearPullerCacheIfNecessary(curTimeSec); + mLastPullerCacheClearTimeSec = curTimeSec; } if (event->GetTagId() != android::util::ISOLATED_UID_CHANGED) { @@ -162,7 +163,7 @@ void StatsLogProcessor::OnLogEvent(LogEvent* event) { // pass the event to metrics managers. for (auto& pair : mMetricsManagers) { pair.second->onLogEvent(*event); - flushIfNecessaryLocked(event->GetTimestampNs(), pair.first, *(pair.second)); + flushIfNecessaryLocked(event->GetElapsedTimestampNs(), pair.first, *(pair.second)); } } @@ -242,6 +243,7 @@ void StatsLogProcessor::onDumpReportLocked(const ConfigKey& key, const uint64_t long long reportsToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS); + int64_t lastReportTimeNs = it->second->getLastReportTimeNs(); // First, fill in ConfigMetricsReport using current data on memory, which // starts from filling in StatsLogReport's. it->second->onDumpReport(dumpTimeStampNs, &proto); @@ -254,10 +256,10 @@ void StatsLogProcessor::onDumpReportLocked(const ConfigKey& key, const uint64_t 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()); + proto.write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_ELAPSED_NANOS, + (long long)lastReportTimeNs); + proto.write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS, + (long long)dumpTimeStampNs); // End of ConfigMetricsReport (reports). proto.end(reportsToken); @@ -340,8 +342,8 @@ void StatsLogProcessor::WriteDataToDisk() { vector<uint8_t> data; onDumpReportLocked(key, time(nullptr) * NS_PER_SEC, &data); // TODO: Add a guardrail to prevent accumulation of file on disk. - string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR, time(nullptr), - key.GetUid(), (long long)key.GetId()); + string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR, + (long)getWallClockSec(), key.GetUid(), (long long)key.GetId()); StorageManager::writeFile(file_name.c_str(), &data[0], data.size()); } } diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index 7ca125a9482f..18ada658e9d8 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -18,6 +18,7 @@ #include "Log.h" #include "StatsService.h" +#include "stats_log_util.h" #include "android-base/stringprintf.h" #include "config/ConfigKey.h" #include "config/ConfigManager.h" @@ -79,18 +80,20 @@ StatsService::StatsService(const sp<Looper>& handlerLooper) mUidMap = new UidMap(); StatsPuller::SetUidMap(mUidMap); mConfigManager = new ConfigManager(); - mProcessor = new StatsLogProcessor(mUidMap, mAnomalyMonitor, time(nullptr), [this](const ConfigKey& key) { - sp<IStatsCompanionService> sc = getStatsCompanionService(); - auto receiver = mConfigManager->GetConfigReceiver(key); - if (sc == nullptr) { - VLOG("Could not find StatsCompanionService"); - } else if (receiver == nullptr) { - VLOG("Statscompanion could not find a broadcast receiver for %s", - key.ToString().c_str()); - } else { - sc->sendDataBroadcast(receiver); + mProcessor = new StatsLogProcessor(mUidMap, mAnomalyMonitor, getElapsedRealtimeSec(), + [this](const ConfigKey& key) { + sp<IStatsCompanionService> sc = getStatsCompanionService(); + auto receiver = mConfigManager->GetConfigReceiver(key); + if (sc == nullptr) { + VLOG("Could not find StatsCompanionService"); + } else if (receiver == nullptr) { + VLOG("Statscompanion could not find a broadcast receiver for %s", + key.ToString().c_str()); + } else { + sc->sendDataBroadcast(receiver); + } } - }); + ); mConfigManager->AddListener(mProcessor); @@ -668,11 +671,7 @@ Status StatsService::informAnomalyAlarmFired() { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call informAnomalyAlarmFired"); } - - // TODO: This may be a bug. time(nullptr) can be off (wrt AlarmManager's time) and cause us to - // miss the alarm! Eventually we will switch to using elapsedRealTime everywhere, - // which may hopefully fix the problem, so we'll leave this alone for now. - uint64_t currentTimeSec = time(nullptr); + uint64_t currentTimeSec = getElapsedRealtimeSec(); std::unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> anomalySet = mAnomalyMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec)); if (anomalySet.size() > 0) { diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp index 06ff603f083f..fbb0fdde40a0 100644 --- a/cmds/statsd/src/config/ConfigManager.cpp +++ b/cmds/statsd/src/config/ConfigManager.cpp @@ -101,7 +101,7 @@ void ConfigManager::RemoveConfig(const ConfigKey& key) { } void ConfigManager::remove_saved_configs(const ConfigKey& key) { - string suffix = StringPrintf("%d-%lld", key.GetUid(), (long long)key.GetId()); + string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId()); StorageManager::deleteSuffixedFiles(STATS_SERVICE_DIR, suffix.c_str()); } diff --git a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp index d0d2f938cf0c..d1d9d3778267 100644 --- a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp +++ b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp @@ -25,6 +25,7 @@ #include "guardrail/StatsdStats.h" #include "logd/LogEvent.h" #include "statslog.h" +#include "stats_log_util.h" using std::make_shared; using std::shared_ptr; @@ -62,7 +63,9 @@ bool CpuTimePerUidFreqPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) { return false; } - uint64_t timestamp = time(nullptr) * NS_PER_SEC; + int64_t wallClockTimestampNs = getWallClockNs(); + int64_t elapsedTimestampNs = getElapsedRealtimeNs(); + char buf[kLineBufferSize]; // first line prints the format and frequencies fin.getline(buf, kLineBufferSize); @@ -77,7 +80,8 @@ bool CpuTimePerUidFreqPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) { int idx = 0; do { timeMs = std::stoull(pch); - auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID_FREQ, timestamp); + auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID_FREQ, + wallClockTimestampNs, elapsedTimestampNs); ptr->write(uid); ptr->write(idx); ptr->write(timeMs); diff --git a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidPuller.cpp index d9aeb4656bfe..568b8f0c0c53 100644 --- a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp +++ b/cmds/statsd/src/external/CpuTimePerUidPuller.cpp @@ -24,6 +24,7 @@ #include "guardrail/StatsdStats.h" #include "logd/LogEvent.h" #include "statslog.h" +#include "stats_log_util.h" using std::make_shared; using std::shared_ptr; @@ -57,7 +58,8 @@ bool CpuTimePerUidPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) { return false; } - uint64_t timestamp = time(nullptr) * NS_PER_SEC; + int64_t wallClockTimestampNs = getWallClockNs(); + int64_t elapsedTimestampNs = getElapsedRealtimeNs(); char buf[kLineBufferSize]; char* pch; while (!fin.eof()) { @@ -70,7 +72,8 @@ bool CpuTimePerUidPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) { pch = strtok(buf, " "); uint64_t sysTimeMs = std::stoull(pch); - auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID, timestamp); + auto ptr = make_shared<LogEvent>(android::util::CPU_TIME_PER_UID, + wallClockTimestampNs, elapsedTimestampNs); ptr->write(uid); ptr->write(userTimeMs); ptr->write(sysTimeMs); diff --git a/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp b/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp index 0e126e7a4b44..0b545ccb3658 100644 --- a/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp +++ b/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp @@ -23,6 +23,7 @@ #include "guardrail/StatsdStats.h" #include "logd/LogEvent.h" #include "statslog.h" +#include "stats_log_util.h" using std::make_shared; using std::shared_ptr; @@ -57,7 +58,9 @@ bool KernelUidCpuActiveTimeReader::PullInternal(vector<shared_ptr<LogEvent>>* da return false; } - uint64_t timestamp = time(nullptr) * NS_PER_SEC; + int64_t wallClockTimestampNs = getWallClockNs(); + int64_t elapsedTimestampNs = getElapsedRealtimeNs(); + char buf[kLineBufferSize]; char* pch; while (!fin.eof()) { @@ -70,7 +73,7 @@ bool KernelUidCpuActiveTimeReader::PullInternal(vector<shared_ptr<LogEvent>>* da int idx = 0; do { timeMs = std::stoull(pch); - auto ptr = make_shared<LogEvent>(mTagId, timestamp); + auto ptr = make_shared<LogEvent>(mTagId, wallClockTimestampNs, elapsedTimestampNs); ptr->write(uid); ptr->write(idx); ptr->write(timeMs); diff --git a/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp b/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp index 7684ed4eb44b..cc80204b105e 100644 --- a/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp +++ b/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp @@ -22,6 +22,7 @@ #include "guardrail/StatsdStats.h" #include "logd/LogEvent.h" #include "statslog.h" +#include "stats_log_util.h" using std::make_shared; using std::shared_ptr; @@ -56,7 +57,8 @@ bool KernelUidCpuClusterTimeReader::PullInternal(vector<shared_ptr<LogEvent>>* d return false; } - uint64_t timestamp = time(nullptr) * NS_PER_SEC; + int64_t wallClockTimestampNs = getWallClockNs(); + int64_t elapsedTimestampNs = getElapsedRealtimeNs(); char buf[kLineBufferSize]; char* pch; while (!fin.eof()) { @@ -69,7 +71,7 @@ bool KernelUidCpuClusterTimeReader::PullInternal(vector<shared_ptr<LogEvent>>* d int idx = 0; do { timeMs = std::stoull(pch); - auto ptr = make_shared<LogEvent>(mTagId, timestamp); + auto ptr = make_shared<LogEvent>(mTagId, wallClockTimestampNs, elapsedTimestampNs); ptr->write(uid); ptr->write(idx); ptr->write(timeMs); diff --git a/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp b/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp index 72fb5ffd4b90..261cb4332dd6 100644 --- a/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp +++ b/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp @@ -25,6 +25,7 @@ #include "ResourceHealthManagerPuller.h" #include "logd/LogEvent.h" #include "statslog.h" +#include "stats_log_util.h" using android::hardware::hidl_vec; using android::hardware::health::V2_0::get_health_service; @@ -61,7 +62,8 @@ bool ResourceHealthManagerPuller::PullInternal(vector<shared_ptr<LogEvent>>* dat return false; } - uint64_t timestamp = time(nullptr) * NS_PER_SEC; + int64_t wallClockTimestampNs = getWallClockNs(); + int64_t elapsedTimestampNs = getElapsedRealtimeNs(); data->clear(); bool result_success = true; @@ -72,12 +74,14 @@ bool ResourceHealthManagerPuller::PullInternal(vector<shared_ptr<LogEvent>>* dat return; } if (mTagId == android::util::REMAINING_BATTERY_CAPACITY) { - auto ptr = make_shared<LogEvent>(android::util::REMAINING_BATTERY_CAPACITY, timestamp); + auto ptr = make_shared<LogEvent>(android::util::REMAINING_BATTERY_CAPACITY, + wallClockTimestampNs, elapsedTimestampNs); ptr->write(v.legacy.batteryChargeCounter); ptr->init(); data->push_back(ptr); } else if (mTagId == android::util::FULL_BATTERY_CAPACITY) { - auto ptr = make_shared<LogEvent>(android::util::FULL_BATTERY_CAPACITY, timestamp); + auto ptr = make_shared<LogEvent>(android::util::FULL_BATTERY_CAPACITY, + wallClockTimestampNs, elapsedTimestampNs); ptr->write(v.legacy.batteryFullCharge); ptr->init(); data->push_back(ptr); diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp index 8210c8dcd63d..bd859fd79a09 100644 --- a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp +++ b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp @@ -22,6 +22,7 @@ #include <private/android_filesystem_config.h> #include "StatsCompanionServicePuller.h" #include "StatsService.h" +#include "stats_log_util.h" #include "guardrail/StatsdStats.h" using namespace android; @@ -53,13 +54,13 @@ bool StatsCompanionServicePuller::PullInternal(vector<shared_ptr<LogEvent> >* da return false; } data->clear(); - int timestamp = time(nullptr); + int32_t timestampSec = getWallClockSec(); for (const StatsLogEventWrapper& it : returned_value) { log_msg tmp; tmp.entry_v1.len = it.bytes.size(); // Manually set the header size to 28 bytes to match the pushed log events. tmp.entry.hdr_size = kLogMsgHeaderSize; - tmp.entry_v1.sec = timestamp; + tmp.entry_v1.sec = timestampSec; // And set the received bytes starting after the 28 bytes reserved for header. std::copy(it.bytes.begin(), it.bytes.end(), tmp.buf + kLogMsgHeaderSize); data->push_back(make_shared<LogEvent>(tmp)); diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp index fc0ad7c5c3fc..9513cc521af7 100644 --- a/cmds/statsd/src/external/StatsPuller.cpp +++ b/cmds/statsd/src/external/StatsPuller.cpp @@ -20,6 +20,7 @@ #include "StatsPuller.h" #include "guardrail/StatsdStats.h" #include "puller_util.h" +#include "stats_log_util.h" namespace android { namespace os { @@ -44,7 +45,7 @@ StatsPuller::StatsPuller(const int tagId) bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) { lock_guard<std::mutex> lock(mLock); StatsdStats::getInstance().notePull(mTagId); - long curTime = time(nullptr); + long curTime = getElapsedRealtimeSec(); if (curTime - mLastPullTimeSec < mCoolDownSec) { (*data) = mCachedData; StatsdStats::getInstance().notePullFromCache(mTagId); diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp index 4c676a70363f..08c59cfed518 100644 --- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp +++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp @@ -33,6 +33,7 @@ #include "SubsystemSleepStatePuller.h" #include "logd/LogEvent.h" #include "statslog.h" +#include "stats_log_util.h" #include <iostream> @@ -165,8 +166,9 @@ void StatsPullerManagerImpl::RegisterReceiver(int tagId, wp<PullDataReceiver> re if (roundedIntervalMs < mCurrentPullingInterval) { VLOG("Updating pulling interval %ld", intervalMs); mCurrentPullingInterval = roundedIntervalMs; - long currentTimeMs = time(nullptr) * 1000; - long nextAlarmTimeMs = currentTimeMs + mCurrentPullingInterval - (currentTimeMs - mTimeBaseSec * 1000) % mCurrentPullingInterval; + long currentTimeMs = getElapsedRealtimeMillis(); + long nextAlarmTimeMs = currentTimeMs + mCurrentPullingInterval - + (currentTimeMs - mTimeBaseSec * 1000) % mCurrentPullingInterval; if (mStatsCompanionService != nullptr) { mStatsCompanionService->setPullingAlarms(nextAlarmTimeMs, mCurrentPullingInterval); } else { @@ -195,7 +197,7 @@ void StatsPullerManagerImpl::UnRegisterReceiver(int tagId, wp<PullDataReceiver> void StatsPullerManagerImpl::OnAlarmFired() { AutoMutex _l(mReceiversLock); - uint64_t currentTimeMs = time(nullptr) /60 * 60 * 1000; + uint64_t currentTimeMs = getElapsedRealtimeMillis(); vector<pair<int, vector<ReceiverInfo*>>> needToPull = vector<pair<int, vector<ReceiverInfo*>>>(); diff --git a/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp b/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp index 65a1df0eda20..4501b64ad47e 100644 --- a/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp +++ b/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp @@ -36,6 +36,7 @@ #include "SubsystemSleepStatePuller.h" #include "logd/LogEvent.h" #include "statslog.h" +#include "stats_log_util.h" using android::hardware::hidl_vec; using android::hardware::power::V1_0::IPower; @@ -84,20 +85,22 @@ bool SubsystemSleepStatePuller::PullInternal(vector<shared_ptr<LogEvent>>* data) return false; } - uint64_t timestamp = time(nullptr) * NS_PER_SEC; + int64_t wallClockTimestampNs = getWallClockNs(); + int64_t elapsedTimestampNs = getElapsedRealtimeNs(); data->clear(); Return<void> ret; ret = gPowerHalV1_0->getPlatformLowPowerStats( - [&data, timestamp](hidl_vec<PowerStatePlatformSleepState> states, Status status) { + [&data, wallClockTimestampNs, elapsedTimestampNs](hidl_vec<PowerStatePlatformSleepState> states, Status status) { if (status != Status::SUCCESS) return; for (size_t i = 0; i < states.size(); i++) { const PowerStatePlatformSleepState& state = states[i]; - auto statePtr = make_shared<LogEvent>(android::util::SUBSYSTEM_SLEEP_STATE, - timestamp); + auto statePtr = make_shared<LogEvent>( + android::util::SUBSYSTEM_SLEEP_STATE, + wallClockTimestampNs, elapsedTimestampNs); statePtr->write(state.name); statePtr->write(""); statePtr->write(state.totalTransitions); @@ -109,8 +112,9 @@ bool SubsystemSleepStatePuller::PullInternal(vector<shared_ptr<LogEvent>>* data) (long long)state.totalTransitions, state.supportedOnlyInSuspend ? 1 : 0); for (auto voter : state.voters) { - auto voterPtr = make_shared<LogEvent>(android::util::SUBSYSTEM_SLEEP_STATE, - timestamp); + auto voterPtr = make_shared<LogEvent>( + android::util::SUBSYSTEM_SLEEP_STATE, + wallClockTimestampNs, elapsedTimestampNs); voterPtr->write(state.name); voterPtr->write(voter.name); voterPtr->write(voter.totalNumberOfTimesVotedSinceBoot); @@ -135,7 +139,7 @@ bool SubsystemSleepStatePuller::PullInternal(vector<shared_ptr<LogEvent>>* data) android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0); if (gPowerHal_1_1 != nullptr) { ret = gPowerHal_1_1->getSubsystemLowPowerStats( - [&data, timestamp](hidl_vec<PowerStateSubsystem> subsystems, Status status) { + [&data, wallClockTimestampNs, elapsedTimestampNs](hidl_vec<PowerStateSubsystem> subsystems, Status status) { if (status != Status::SUCCESS) return; if (subsystems.size() > 0) { @@ -145,7 +149,8 @@ bool SubsystemSleepStatePuller::PullInternal(vector<shared_ptr<LogEvent>>* data) const PowerStateSubsystemSleepState& state = subsystem.states[j]; auto subsystemStatePtr = make_shared<LogEvent>( - android::util::SUBSYSTEM_SLEEP_STATE, timestamp); + android::util::SUBSYSTEM_SLEEP_STATE, + wallClockTimestampNs, elapsedTimestampNs); subsystemStatePtr->write(subsystem.name); subsystemStatePtr->write(state.name); subsystemStatePtr->write(state.totalTransitions); diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp index 06c5b0049a3b..e2e94263ed8f 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.cpp +++ b/cmds/statsd/src/guardrail/StatsdStats.cpp @@ -80,7 +80,7 @@ std::map<int, long> StatsdStats::kPullerCooldownMap = { // TODO: add stats for pulled atoms. StatsdStats::StatsdStats() { mPushedAtomStats.resize(android::util::kMaxPushedAtomId + 1); - mStartTimeSec = time(nullptr); + mStartTimeSec = getWallClockSec(); } StatsdStats& StatsdStats::getInstance() { @@ -99,7 +99,7 @@ void StatsdStats::addToIceBoxLocked(const StatsdStatsReport_ConfigStats& stats) void StatsdStats::noteConfigReceived(const ConfigKey& key, int metricsCount, int conditionsCount, int matchersCount, int alertsCount, bool isValid) { lock_guard<std::mutex> lock(mLock); - int32_t nowTimeSec = time(nullptr); + int32_t nowTimeSec = getWallClockSec(); // If there is an existing config for the same key, icebox the old config. noteConfigRemovedInternalLocked(key); @@ -125,7 +125,7 @@ void StatsdStats::noteConfigReceived(const ConfigKey& key, int metricsCount, int void StatsdStats::noteConfigRemovedInternalLocked(const ConfigKey& key) { auto it = mConfigStats.find(key); if (it != mConfigStats.end()) { - int32_t nowTimeSec = time(nullptr); + int32_t nowTimeSec = getWallClockSec(); it->second.set_deletion_time_sec(nowTimeSec); // Add condition stats, metrics stats, matcher stats, alert stats addSubStatsToConfigLocked(key, it->second); @@ -145,7 +145,7 @@ void StatsdStats::noteConfigRemoved(const ConfigKey& key) { } void StatsdStats::noteBroadcastSent(const ConfigKey& key) { - noteBroadcastSent(key, time(nullptr)); + noteBroadcastSent(key, getWallClockSec()); } void StatsdStats::noteBroadcastSent(const ConfigKey& key, int32_t timeSec) { @@ -164,7 +164,7 @@ void StatsdStats::noteBroadcastSent(const ConfigKey& key, int32_t timeSec) { } void StatsdStats::noteDataDropped(const ConfigKey& key) { - noteDataDropped(key, time(nullptr)); + noteDataDropped(key, getWallClockSec()); } void StatsdStats::noteDataDropped(const ConfigKey& key, int32_t timeSec) { @@ -183,7 +183,7 @@ void StatsdStats::noteDataDropped(const ConfigKey& key, int32_t timeSec) { } void StatsdStats::noteMetricsReportSent(const ConfigKey& key) { - noteMetricsReportSent(key, time(nullptr)); + noteMetricsReportSent(key, getWallClockSec()); } void StatsdStats::noteMetricsReportSent(const ConfigKey& key, int32_t timeSec) { @@ -275,10 +275,6 @@ void StatsdStats::notePullFromCache(int pullAtomId) { void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) { lock_guard<std::mutex> lock(mLock); - if (timeSec < mStartTimeSec) { - return; - } - if (atomId > android::util::kMaxPushedAtomId) { ALOGW("not interested in atom %d", atomId); return; @@ -293,7 +289,7 @@ void StatsdStats::noteLoggerError(int error) { if (mLoggerErrors.size() == kMaxLoggerErrors) { mLoggerErrors.pop_front(); } - mLoggerErrors.push_back(std::make_pair(time(nullptr), error)); + mLoggerErrors.push_back(std::make_pair(getWallClockSec(), error)); } void StatsdStats::reset() { @@ -303,7 +299,7 @@ void StatsdStats::reset() { void StatsdStats::resetInternalLocked() { // Reset the historical data, but keep the active ConfigStats - mStartTimeSec = time(nullptr); + mStartTimeSec = getWallClockSec(); mIceBox.clear(); mConditionStats.clear(); mMetricsStats.clear(); @@ -495,7 +491,7 @@ void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) { ProtoOutputStream proto; proto.write(FIELD_TYPE_INT32 | FIELD_ID_BEGIN_TIME, mStartTimeSec); - proto.write(FIELD_TYPE_INT32 | FIELD_ID_END_TIME, (int32_t)time(nullptr)); + proto.write(FIELD_TYPE_INT32 | FIELD_ID_END_TIME, (int32_t)getWallClockSec()); for (const auto& configStats : mIceBox) { const int numBytes = configStats.ByteSize(); diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp index ce3a4b96b261..7489d9b72e94 100644 --- a/cmds/statsd/src/logd/LogEvent.cpp +++ b/cmds/statsd/src/logd/LogEvent.cpp @@ -33,7 +33,7 @@ using android::util::ProtoOutputStream; LogEvent::LogEvent(log_msg& msg) { mContext = create_android_log_parser(msg.msg() + sizeof(uint32_t), msg.len() - sizeof(uint32_t)); - mTimestampNs = msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec; + mLogdTimestampNs = msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec; mLogUid = msg.entry_v4.uid; init(mContext); if (mContext) { @@ -42,12 +42,24 @@ LogEvent::LogEvent(log_msg& msg) { } } -LogEvent::LogEvent(int32_t tagId, uint64_t timestampNs) { - mTimestampNs = timestampNs; +LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs) { + mLogdTimestampNs = wallClockTimestampNs; mTagId = tagId; mLogUid = 0; mContext = create_android_logger(1937006964); // the event tag shared by all stats logs if (mContext) { + android_log_write_int64(mContext, elapsedTimestampNs); + android_log_write_int32(mContext, tagId); + } +} + +LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) { + mLogdTimestampNs = timestampNs; + mTagId = tagId; + mLogUid = 0; + mContext = create_android_logger(1937006964); // the event tag shared by all stats logs + if (mContext) { + android_log_write_int64(mContext, timestampNs); android_log_write_int32(mContext, tagId); } } @@ -176,8 +188,8 @@ void LogEvent::init(android_log_context context) { elem = android_log_read_next(context); switch ((int)elem.type) { case EVENT_TYPE_INT: - // elem at [0] is EVENT_TYPE_LIST, [1] is the tag id. - if (i == 1) { + // elem at [0] is EVENT_TYPE_LIST, [1] is the timestamp, [2] is tag id. + if (i == 2) { mTagId = elem.data.int32; } else { if (depth < 0 || depth > 2) { @@ -214,15 +226,18 @@ void LogEvent::init(android_log_context context) { } break; case EVENT_TYPE_LONG: { - if (depth < 0 || depth > 2) { - ALOGE("Depth > 2. Not supported!"); - return; - } - mValues.push_back( - FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64))); - - pos[depth]++; + if (i == 1) { + mElapsedTimestampNs = elem.data.int64; + } else { + if (depth < 0 || depth > 2) { + ALOGE("Depth > 2. Not supported!"); + return; + } + mValues.push_back( + FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64))); + pos[depth]++; + } } break; case EVENT_TYPE_LIST: depth++; @@ -268,7 +283,9 @@ int64_t LogEvent::GetLong(size_t key, status_t* err) const { int field = getSimpleField(key); for (const auto& value : mValues) { if (value.mField.getField() == field) { - if (value.mValue.getType() == INT) { + if (value.mValue.getType() == LONG) { + return value.mValue.long_value; + } else if (value.mValue.getType() == INT) { return value.mValue.int_value; } else { *err = BAD_TYPE; @@ -368,7 +385,7 @@ float LogEvent::GetFloat(size_t key, status_t* err) const { string LogEvent::ToString() const { ostringstream result; - result << "{ " << mTimestampNs << " (" << mTagId << ")"; + result << "{ " << mLogdTimestampNs << " " << mElapsedTimestampNs << " (" << mTagId << ")"; for (const auto& value : mValues) { result << StringPrintf("%#x", value.mField.getField()); result << "->"; diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h index 0895daa49ad3..b3084d54d848 100644 --- a/cmds/statsd/src/logd/LogEvent.h +++ b/cmds/statsd/src/logd/LogEvent.h @@ -47,14 +47,18 @@ public: /** * Constructs a LogEvent with synthetic data for testing. Must call init() before reading. */ - explicit LogEvent(int32_t tagId, uint64_t timestampNs); + explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs); + + // For testing. The timestamp is used as both elapsed real time and logd timestamp. + explicit LogEvent(int32_t tagId, int64_t timestampNs); ~LogEvent(); /** * Get the timestamp associated with this event. */ - inline uint64_t GetTimestampNs() const { return mTimestampNs; } + inline int64_t GetLogdTimestampNs() const { return mLogdTimestampNs; } + inline int64_t GetElapsedTimestampNs() const { return mElapsedTimestampNs; } /** * Get the tag for this event. @@ -107,9 +111,18 @@ public: void init(); /** - * Set timestamp if the original timestamp is missing. + * Set elapsed timestamp if the original timestamp is missing. */ - void setTimestampNs(uint64_t timestampNs) {mTimestampNs = timestampNs;} + void setElapsedTimestampNs(int64_t timestampNs) { + mElapsedTimestampNs = timestampNs; + } + + /** + * Set the timestamp if the original logd timestamp is missing. + */ + void setLogdWallClockTimestampNs(int64_t timestampNs) { + mLogdTimestampNs = timestampNs; + } inline int size() const { return mValues.size(); @@ -144,7 +157,11 @@ private: // When the log event is created from log msg, this field is never initiated. android_log_context mContext = NULL; - uint64_t mTimestampNs; + // The timestamp set by the logd. + int64_t mLogdTimestampNs; + + // The elapsed timestamp set by statsd log writer. + int64_t mElapsedTimestampNs; int mTagId; diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp index bd2674b86a46..178db1ae5e5f 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.cpp +++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp @@ -52,8 +52,8 @@ const int FIELD_ID_DIMENSION_IN_WHAT = 1; const int FIELD_ID_DIMENSION_IN_CONDITION = 2; const int FIELD_ID_BUCKET_INFO = 3; // for CountBucketInfo -const int FIELD_ID_START_BUCKET_NANOS = 1; -const int FIELD_ID_END_BUCKET_NANOS = 2; +const int FIELD_ID_START_BUCKET_ELAPSED_NANOS = 1; +const int FIELD_ID_END_BUCKET_ELAPSED_NANOS = 2; const int FIELD_ID_COUNT = 3; CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric& metric, @@ -107,7 +107,6 @@ void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, if (mPastBuckets.empty()) { return; } - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId); long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_COUNT_METRICS); @@ -132,12 +131,13 @@ void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, } // Then fill bucket_info (CountBucketInfo). + for (const auto& bucket : counter.second) { long long bucketInfoToken = protoOutput->start( FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS, + protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_ELAPSED_NANOS, (long long)bucket.mBucketStartNs); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS, + protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_ELAPSED_NANOS, (long long)bucket.mBucketEndNs); protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_COUNT, (long long)bucket.mCount); protoOutput->end(bucketInfoToken); @@ -184,7 +184,7 @@ void CountMetricProducer::onMatchedLogEventInternalLocked( const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKey, bool condition, const LogEvent& event) { - uint64_t eventTimeNs = event.GetTimestampNs(); + uint64_t eventTimeNs = event.GetElapsedTimestampNs(); flushIfNeededLocked(eventTimeNs); if (condition == false) { diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp index 6b321e11edcf..af22578cc758 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp +++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp @@ -51,8 +51,8 @@ const int FIELD_ID_DIMENSION_IN_WHAT = 1; const int FIELD_ID_DIMENSION_IN_CONDITION = 2; const int FIELD_ID_BUCKET_INFO = 3; // for DurationBucketInfo -const int FIELD_ID_START_BUCKET_NANOS = 1; -const int FIELD_ID_END_BUCKET_NANOS = 2; +const int FIELD_ID_START_BUCKET_ELAPSED_NANOS = 1; +const int FIELD_ID_END_BUCKET_ELAPSED_NANOS = 2; const int FIELD_ID_DURATION = 3; DurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const DurationMetric& metric, @@ -221,9 +221,9 @@ void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, for (const auto& bucket : pair.second) { long long bucketInfoToken = protoOutput->start( FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS, + protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_ELAPSED_NANOS, (long long)bucket.mBucketStartNs); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS, + protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_ELAPSED_NANOS, (long long)bucket.mBucketEndNs); protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DURATION, (long long)bucket.mDuration); protoOutput->end(bucketInfoToken); @@ -310,11 +310,11 @@ void DurationMetricProducer::onMatchedLogEventInternalLocked( const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKeys, bool condition, const LogEvent& event) { - flushIfNeededLocked(event.GetTimestampNs()); + flushIfNeededLocked(event.GetElapsedTimestampNs()); if (matcherIndex == mStopAllIndex) { for (auto& pair : mCurrentSlicedDurationTrackerMap) { - pair.second->noteStopAll(event.GetTimestampNs()); + pair.second->noteStopAll(event.GetElapsedTimestampNs()); } return; } @@ -333,16 +333,16 @@ void DurationMetricProducer::onMatchedLogEventInternalLocked( if (values.empty()) { if (matcherIndex == mStartIndex) { it->second->noteStart(DEFAULT_DIMENSION_KEY, condition, - event.GetTimestampNs(), conditionKeys); + event.GetElapsedTimestampNs(), conditionKeys); } else if (matcherIndex == mStopIndex) { - it->second->noteStop(DEFAULT_DIMENSION_KEY, event.GetTimestampNs(), false); + it->second->noteStop(DEFAULT_DIMENSION_KEY, event.GetElapsedTimestampNs(), false); } } else { for (const auto& value : values) { if (matcherIndex == mStartIndex) { - it->second->noteStart(value, condition, event.GetTimestampNs(), conditionKeys); + it->second->noteStart(value, condition, event.GetElapsedTimestampNs(), conditionKeys); } else if (matcherIndex == mStopIndex) { - it->second->noteStop(value, event.GetTimestampNs(), false); + it->second->noteStop(value, event.GetElapsedTimestampNs(), false); } } } diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp index ed7e44de09c0..2585aa3bdbff 100644 --- a/cmds/statsd/src/metrics/EventMetricProducer.cpp +++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp @@ -19,6 +19,7 @@ #include "EventMetricProducer.h" #include "stats_util.h" +#include "stats_log_util.h" #include <limits.h> #include <stdlib.h> @@ -46,8 +47,9 @@ const int FIELD_ID_EVENT_METRICS = 4; // for EventMetricDataWrapper const int FIELD_ID_DATA = 1; // for EventMetricData -const int FIELD_ID_TIMESTAMP_NANOS = 1; +const int FIELD_ID_ELAPSED_TIMESTAMP_NANOS = 1; const int FIELD_ID_ATOMS = 2; +const int FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS = 3; EventMetricProducer::EventMetricProducer(const ConfigKey& key, const EventMetric& metric, const int conditionIndex, @@ -127,9 +129,12 @@ void EventMetricProducer::onMatchedLogEventInternalLocked( long long wrapperToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA); - mProto->write(FIELD_TYPE_INT64 | FIELD_ID_TIMESTAMP_NANOS, (long long)event.GetTimestampNs()); + mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS, + (long long)event.GetElapsedTimestampNs()); long long eventToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOMS); event.ToProto(*mProto); + mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS, + (long long)getWallClockNs()); mProto->end(eventToken); mProto->end(wrapperToken); } diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index da0cafeca427..af3b4c5a648a 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -52,10 +52,10 @@ const int FIELD_ID_DIMENSION_IN_WHAT = 1; const int FIELD_ID_DIMENSION_IN_CONDITION = 2; const int FIELD_ID_BUCKET_INFO = 3; // for GaugeBucketInfo -const int FIELD_ID_START_BUCKET_NANOS = 1; -const int FIELD_ID_END_BUCKET_NANOS = 2; +const int FIELD_ID_START_BUCKET_ELAPSED_NANOS = 1; +const int FIELD_ID_END_BUCKET_ELAPSED_NANOS = 2; const int FIELD_ID_ATOM = 3; -const int FIELD_ID_TIMESTAMP = 4; +const int FIELD_ID_ELAPSED_ATOM_TIMESTAMP = 4; GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric, const int conditionIndex, @@ -161,9 +161,9 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, for (const auto& bucket : pair.second) { long long bucketInfoToken = protoOutput->start( FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS, + protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_ELAPSED_NANOS, (long long)bucket.mBucketStartNs); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS, + protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_ELAPSED_NANOS, (long long)bucket.mBucketEndNs); if (!bucket.mGaugeAtoms.empty()) { @@ -175,8 +175,9 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, protoOutput->end(atomsToken); for (const auto& atom : bucket.mGaugeAtoms) { - protoOutput->write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_TIMESTAMP, - (long long)atom.mTimestamps); + protoOutput->write( + FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_ELAPSED_ATOM_TIMESTAMP, + (long long)atom.mTimestamps); } } protoOutput->end(bucketInfoToken); @@ -293,7 +294,7 @@ void GaugeMetricProducer::onMatchedLogEventInternalLocked( if (condition == false) { return; } - uint64_t eventTimeNs = event.GetTimestampNs(); + uint64_t eventTimeNs = event.GetElapsedTimestampNs(); mTagId = event.GetTagId(); if (eventTimeNs < mCurrentBucketStartTimeNs) { VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs, diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp index beb90155f183..f3307dc1d1e3 100644 --- a/cmds/statsd/src/metrics/MetricProducer.cpp +++ b/cmds/statsd/src/metrics/MetricProducer.cpp @@ -25,7 +25,7 @@ namespace statsd { using std::map; void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) { - uint64_t eventTimeNs = event.GetTimestampNs(); + uint64_t eventTimeNs = event.GetElapsedTimestampNs(); // this is old event, maybe statsd restarted? if (eventTimeNs < mStartTimeNs) { return; diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index 53cb19374d80..66e1aeb8f43e 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -26,6 +26,7 @@ #include "matchers/SimpleLogMatchingTracker.h" #include "metrics_manager_util.h" #include "stats_util.h" +#include "stats_log_util.h" #include <log/logprint.h> #include <private/android_filesystem_config.h> @@ -49,9 +50,10 @@ const int FIELD_ID_METRICS = 1; MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config, const long timeBaseSec, sp<UidMap> uidMap) - : mConfigKey(key), mUidMap(uidMap), mLastReportTimeNs(0) { + : mConfigKey(key), mUidMap(uidMap), mLastReportTimeNs(timeBaseSec * NS_PER_SEC) { mConfigValid = - initStatsdConfig(key, config, *uidMap, timeBaseSec, mTagIds, mAllAtomMatchers, mAllConditionTrackers, + initStatsdConfig(key, config, *uidMap, timeBaseSec, mTagIds, mAllAtomMatchers, + mAllConditionTrackers, mAllMetricProducers, mAllAnomalyTrackers, mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap, mNoReportMetricIds); @@ -176,7 +178,7 @@ void MetricsManager::onDumpReport(const uint64_t dumpTimeStampNs, ProtoOutputStr protoOutput->end(token); } } - mLastReportTimeNs = ::android::elapsedRealtimeNano(); + mLastReportTimeNs = dumpTimeStampNs; VLOG("=========================Metric Reports End=========================="); } @@ -230,7 +232,7 @@ void MetricsManager::onLogEvent(const LogEvent& event) { } int tagId = event.GetTagId(); - uint64_t eventTime = event.GetTimestampNs(); + uint64_t eventTime = event.GetElapsedTimestampNs(); if (mTagIds.find(tagId) == mTagIds.end()) { // not interesting... return; diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index 45b4ac0cd43a..cbca884ae6f3 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -219,19 +219,19 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven } // For scheduled pulled data, the effective event time is snap to the nearest // bucket boundary to make bucket finalize. - uint64_t realEventTime = allData.at(0)->GetTimestampNs(); + uint64_t realEventTime = allData.at(0)->GetElapsedTimestampNs(); uint64_t eventTime = mStartTimeNs + - ((realEventTime - mStartTimeNs)/mBucketSizeNs) * mBucketSizeNs; + ((realEventTime - mStartTimeNs) / mBucketSizeNs) * mBucketSizeNs; mCondition = false; for (const auto& data : allData) { - data->setTimestampNs(eventTime-1); + data->setElapsedTimestampNs(eventTime - 1); onMatchedLogEventLocked(0, *data); } mCondition = true; for (const auto& data : allData) { - data->setTimestampNs(eventTime); + data->setElapsedTimestampNs(eventTime); onMatchedLogEventLocked(0, *data); } } @@ -261,7 +261,7 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked( const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKey, bool condition, const LogEvent& event) { - uint64_t eventTimeNs = event.GetTimestampNs(); + uint64_t eventTimeNs = event.GetElapsedTimestampNs(); if (eventTimeNs < mCurrentBucketStartTimeNs) { VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs, (long long)mCurrentBucketStartTimeNs); diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index 6701a46acde1..b518f2f841cf 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -62,7 +62,7 @@ public: // Pretend the pulled data occurs right before the app upgrade event. mCondition = false; for (const auto& data : allData) { - data->setTimestampNs(eventTimeNs - 1); + data->setElapsedTimestampNs(eventTimeNs - 1); onMatchedLogEventLocked(0, *data); } @@ -71,7 +71,7 @@ public: mCondition = true; for (const auto& data : allData) { - data->setTimestampNs(eventTimeNs); + data->setElapsedTimestampNs(eventTimeNs); onMatchedLogEventLocked(0, *data); } } else { // For pushed value metric, we simply flush and reset the current bucket start. diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp index 691423e054b2..e322ca4bb1ac 100644 --- a/cmds/statsd/src/packages/UidMap.cpp +++ b/cmds/statsd/src/packages/UidMap.cpp @@ -16,6 +16,7 @@ #define DEBUG true // STOPSHIP if true #include "Log.h" +#include "stats_log_util.h" #include "guardrail/StatsdStats.h" #include "packages/UidMap.h" @@ -82,7 +83,7 @@ int64_t UidMap::getAppVersion(int uid, const string& packageName) const { void UidMap::updateMap(const vector<int32_t>& uid, const vector<int64_t>& versionCode, const vector<String16>& packageName) { - updateMap(time(nullptr) * NS_PER_SEC, uid, versionCode, packageName); + updateMap(getElapsedRealtimeNs(), uid, versionCode, packageName); } void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid, @@ -98,7 +99,7 @@ void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid, } auto snapshot = mOutput.add_snapshots(); - snapshot->set_timestamp_nanos(timestamp); + snapshot->set_elapsed_timestamp_nanos(timestamp); for (size_t j = 0; j < uid.size(); j++) { auto t = snapshot->add_package_info(); t->set_name(string(String8(packageName[j]).string())); @@ -125,7 +126,7 @@ void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid, } void UidMap::updateApp(const String16& app_16, const int32_t& uid, const int64_t& versionCode) { - updateApp(time(nullptr) * NS_PER_SEC, app_16, uid, versionCode); + updateApp(getElapsedRealtimeNs(), app_16, uid, versionCode); } void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid, @@ -137,7 +138,7 @@ void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const i auto log = mOutput.add_changes(); log->set_deletion(false); - log->set_timestamp_nanos(timestamp); + log->set_elapsed_timestamp_nanos(timestamp); log->set_app(appName); log->set_uid(uid); log->set_version(versionCode); @@ -194,7 +195,7 @@ void UidMap::ensureBytesUsedBelowLimit() { } void UidMap::removeApp(const String16& app_16, const int32_t& uid) { - removeApp(time(nullptr) * NS_PER_SEC, app_16, uid); + removeApp(getElapsedRealtimeNs(), app_16, uid); } void UidMap::getListenerListCopyLocked(vector<wp<PackageInfoListener>>* output) { @@ -218,7 +219,7 @@ void UidMap::removeApp(const int64_t& timestamp, const String16& app_16, const i auto log = mOutput.add_changes(); log->set_deletion(true); - log->set_timestamp_nanos(timestamp); + log->set_elapsed_timestamp_nanos(timestamp); log->set_app(app); log->set_uid(uid); mBytesUsed += log->ByteSize(); @@ -305,7 +306,7 @@ size_t UidMap::getBytesUsed() const { } UidMapping UidMap::getOutput(const ConfigKey& key) { - return getOutput(time(nullptr) * NS_PER_SEC, key); + return getOutput(getElapsedRealtimeNs(), key); } UidMapping UidMap::getOutput(const int64_t& timestamp, const ConfigKey& key) { @@ -321,7 +322,7 @@ UidMapping UidMap::getOutput(const int64_t& timestamp, const ConfigKey& key) { auto snapshots = mOutput.mutable_snapshots(); auto it_snapshots = snapshots->cbegin(); while (it_snapshots != snapshots->cend()) { - if (it_snapshots->timestamp_nanos() < cutoff_nanos) { + if (it_snapshots->elapsed_timestamp_nanos() < cutoff_nanos) { // it_snapshots points to the following element after erasing. it_snapshots = snapshots->erase(it_snapshots); } else { @@ -331,7 +332,7 @@ UidMapping UidMap::getOutput(const int64_t& timestamp, const ConfigKey& key) { auto deltas = mOutput.mutable_changes(); auto it_deltas = deltas->cbegin(); while (it_deltas != deltas->cend()) { - if (it_deltas->timestamp_nanos() < cutoff_nanos) { + if (it_deltas->elapsed_timestamp_nanos() < cutoff_nanos) { // it_snapshots points to the following element after erasing. it_deltas = deltas->erase(it_deltas); } else { @@ -343,7 +344,7 @@ UidMapping UidMap::getOutput(const int64_t& timestamp, const ConfigKey& key) { // Produce another snapshot. This results in extra data being uploaded but helps // ensure we can re-construct the UID->app name, versionCode mapping in server. auto snapshot = mOutput.add_snapshots(); - snapshot->set_timestamp_nanos(timestamp); + snapshot->set_elapsed_timestamp_nanos(timestamp); for (auto it : mMap) { auto t = snapshot->add_package_info(); t->set_name(it.second.packageName); diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index b56cffb40806..b427485fd705 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -42,15 +42,17 @@ message DimensionsValueTuple { } message EventMetricData { - optional int64 timestamp_nanos = 1; + optional int64 elapsed_timestamp_nanos = 1; optional Atom atom = 2; + + optional int64 wall_clock_timestamp_sec = 3; } message CountBucketInfo { - optional int64 start_bucket_nanos = 1; + optional int64 start_bucket_elapsed_nanos = 1; - optional int64 end_bucket_nanos = 2; + optional int64 end_bucket_elapsed_nanos = 2; optional int64 count = 3; } @@ -64,9 +66,9 @@ message CountMetricData { } message DurationBucketInfo { - optional int64 start_bucket_nanos = 1; + optional int64 start_bucket_elapsed_nanos = 1; - optional int64 end_bucket_nanos = 2; + optional int64 end_bucket_elapsed_nanos = 2; optional int64 duration_nanos = 3; } @@ -80,9 +82,9 @@ message DurationMetricData { } message ValueBucketInfo { - optional int64 start_bucket_nanos = 1; + optional int64 start_bucket_elapsed_nanos = 1; - optional int64 end_bucket_nanos = 2; + optional int64 end_bucket_elapsed_nanos = 2; optional int64 value = 3; } @@ -102,7 +104,7 @@ message GaugeBucketInfo { repeated Atom atom = 3; - repeated int64 timestamp_nanos = 4; + repeated int64 elapsed_timestamp_nanos = 4; } message GaugeMetricData { @@ -122,7 +124,7 @@ message UidMapping { optional int32 uid = 3; } - optional int64 timestamp_nanos = 1; + optional int64 elapsed_timestamp_nanos = 1; repeated PackageInfo package_info = 2; } @@ -131,7 +133,7 @@ message UidMapping { message Change { optional bool deletion = 1; - optional int64 timestamp_nanos = 2; + optional int64 elapsed_timestamp_nanos = 2; optional string app = 3; optional int32 uid = 4; @@ -176,9 +178,9 @@ message ConfigMetricsReport { optional UidMapping uid_map = 2; - optional int64 last_report_nanos = 3; + optional int64 last_report_elapsed_nanos = 3; - optional int64 current_report_nanos = 4; + optional int64 current_report_elapsed_nanos = 4; } message ConfigMetricsReportList { diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp index 86c258bd3dfd..e73577041f75 100644 --- a/cmds/statsd/src/stats_log_util.cpp +++ b/cmds/statsd/src/stats_log_util.cpp @@ -20,6 +20,8 @@ #include <utils/Log.h> #include <set> #include <stack> +#include <utils/Log.h> +#include <utils/SystemClock.h> using android::util::FIELD_COUNT_REPEATED; using android::util::FIELD_TYPE_BOOL; @@ -263,6 +265,30 @@ void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats> protoOutput->end(token); } +int64_t getElapsedRealtimeNs() { + return ::android::elapsedRealtimeNano(); +} + +int64_t getElapsedRealtimeSec() { + return ::android::elapsedRealtimeNano() / NS_PER_SEC; +} + +int64_t getElapsedRealtimeMillis() { + return ::android::elapsedRealtime(); +} + +int64_t getWallClockNs() { + return time(nullptr) * NS_PER_SEC; +} + +int64_t getWallClockSec() { + return time(nullptr); +} + +int64_t getWallClockMillis() { + return time(nullptr) * MS_PER_SEC; +} + } // namespace statsd } // namespace os } // namespace android
\ No newline at end of file diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h index 6583f579648b..32fe0b8370b8 100644 --- a/cmds/statsd/src/stats_log_util.h +++ b/cmds/statsd/src/stats_log_util.h @@ -35,6 +35,24 @@ void writeDimensionToProto(const HashableDimensionKey& dimension, // Convert the TimeUnit enum to the bucket size in millis. int64_t TimeUnitToBucketSizeInMillis(TimeUnit unit); +// Gets the elapsed timestamp in ns. +int64_t getElapsedRealtimeNs(); + +// Gets the elapsed timestamp in millis. +int64_t getElapsedRealtimeMillis(); + +// Gets the elapsed timestamp in seconds. +int64_t getElapsedRealtimeSec(); + +// Gets the wall clock timestamp in ns. +int64_t getWallClockNs(); + +// Gets the wall clock timestamp in millis. +int64_t getWallClockMillis(); + +// Gets the wall clock timestamp in seconds. +int64_t getWallClockSec(); + // Helper function to write PulledAtomStats to ProtoOutputStream void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair, util::ProtoOutputStream* protoOutput); diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp index 23bd55616be2..6a1db72b3911 100644 --- a/cmds/statsd/src/storage/StorageManager.cpp +++ b/cmds/statsd/src/storage/StorageManager.cpp @@ -20,6 +20,7 @@ #include "android-base/stringprintf.h" #include "guardrail/StatsdStats.h" #include "storage/StorageManager.h" +#include "stats_log_util.h" #include <android-base/file.h> #include <dirent.h> @@ -252,7 +253,7 @@ void StorageManager::trimToFit(const char* path) { string file_name = getFilePath(path, timestamp, uid, configID); // Check for timestamp and delete if it's too old. - long fileAge = time(nullptr) - timestamp; + long fileAge = getWallClockSec() - timestamp; if (fileAge > StatsdStats::kMaxAgeSecond) { deleteFile(file_name.c_str()); } diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp index 01743ef1a45c..93cd5875c52b 100644 --- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp @@ -163,11 +163,11 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSlice) { "App1"); EXPECT_EQ(data.bucket_info_size(), 2); EXPECT_EQ(data.bucket_info(0).count(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.bucket_info(1).count(), 1); - EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); data = countMetrics.data(1); ValidateAttributionUidAndTagDimension( @@ -175,11 +175,11 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSlice) { "GMSCoreModule1"); EXPECT_EQ(data.bucket_info_size(), 2); EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.bucket_info(1).count(), 1); - EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); data = countMetrics.data(2); ValidateAttributionUidAndTagDimension( @@ -187,8 +187,8 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSlice) { "GMSCoreModule3"); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 4 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 4 * bucketSizeNs); data = countMetrics.data(3); ValidateAttributionUidAndTagDimension( @@ -196,8 +196,8 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSlice) { "GMSCoreModule2"); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); } #else diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp index 275b58244e0f..293f579ac848 100644 --- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp @@ -142,8 +142,8 @@ TEST(DimensionInConditionE2eTest, TestCountMetricNoLink) { auto data = countMetrics.data(0); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); @@ -153,8 +153,8 @@ TEST(DimensionInConditionE2eTest, TestCountMetricNoLink) { data = countMetrics.data(1); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); @@ -165,8 +165,8 @@ TEST(DimensionInConditionE2eTest, TestCountMetricNoLink) { data = countMetrics.data(2); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 3); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); @@ -177,11 +177,11 @@ TEST(DimensionInConditionE2eTest, TestCountMetricNoLink) { data = countMetrics.data(3); EXPECT_EQ(data.bucket_info_size(), 2); EXPECT_EQ(data.bucket_info(0).count(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.bucket_info(1).count(), 1); - EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); @@ -192,8 +192,8 @@ TEST(DimensionInConditionE2eTest, TestCountMetricNoLink) { data = countMetrics.data(4); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); @@ -203,8 +203,8 @@ TEST(DimensionInConditionE2eTest, TestCountMetricNoLink) { data = countMetrics.data(5); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); @@ -215,8 +215,8 @@ TEST(DimensionInConditionE2eTest, TestCountMetricNoLink) { data = countMetrics.data(6); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.dimensions_in_what().field(), android::util::SCREEN_BRIGHTNESS_CHANGED); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); @@ -358,8 +358,8 @@ TEST(DimensionInConditionE2eTest, TestCountMetricWithLink) { EXPECT_FALSE(data.dimensions_in_condition().has_field()); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); data = countMetrics.data(1); EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); @@ -370,8 +370,8 @@ TEST(DimensionInConditionE2eTest, TestCountMetricWithLink) { android::util::SYNC_STATE_CHANGED, 111, "App1"); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); data = countMetrics.data(2); EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); @@ -381,8 +381,8 @@ TEST(DimensionInConditionE2eTest, TestCountMetricWithLink) { EXPECT_FALSE(data.dimensions_in_condition().has_field()); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 2); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); data = countMetrics.data(3); EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); @@ -393,11 +393,11 @@ TEST(DimensionInConditionE2eTest, TestCountMetricWithLink) { android::util::SYNC_STATE_CHANGED, 333, "App2"); EXPECT_EQ(data.bucket_info_size(), 2); EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.bucket_info(1).count(), 1); - EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); data = countMetrics.data(4); EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED); @@ -407,8 +407,8 @@ TEST(DimensionInConditionE2eTest, TestCountMetricWithLink) { EXPECT_FALSE(data.dimensions_in_condition().has_field()); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).count(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); } namespace { @@ -531,11 +531,11 @@ TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink) { EXPECT_FALSE(data.dimensions_in_condition().has_field()); EXPECT_EQ(data.bucket_info_size(), 2); EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.bucket_info(1).duration_nanos(), 30); - EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); data = metrics.data(1); EXPECT_FALSE(data.dimensions_in_what().has_field()); @@ -543,11 +543,11 @@ TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink) { android::util::SYNC_STATE_CHANGED, 111, "App1"); EXPECT_EQ(data.bucket_info_size(), 2); EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 201 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.bucket_info(1).duration_nanos(), 300); - EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); data = metrics.data(2); EXPECT_FALSE(data.dimensions_in_what().has_field()); @@ -555,11 +555,11 @@ TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink) { android::util::SYNC_STATE_CHANGED, 333, "App2"); EXPECT_EQ(data.bucket_info_size(), 2); EXPECT_EQ(data.bucket_info(0).duration_nanos(), 500 - 401 + bucketSizeNs - 600); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); - EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); } } @@ -693,8 +693,8 @@ TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink) { EXPECT_FALSE(data.dimensions_in_condition().has_field()); EXPECT_EQ(data.bucket_info_size(), 1); EXPECT_EQ(data.bucket_info(0).duration_nanos(), 9); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); data = metrics.data(1); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); @@ -703,11 +703,11 @@ TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink) { android::util::SYNC_STATE_CHANGED, 111, "App1"); EXPECT_EQ(data.bucket_info_size(), 2); EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 201); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100); - EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); data = metrics.data(2); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1); @@ -716,11 +716,11 @@ TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink) { android::util::SYNC_STATE_CHANGED, 333, "App2"); EXPECT_EQ(data.bucket_info_size(), 2); EXPECT_EQ(data.bucket_info(0).duration_nanos(), bucketSizeNs - 401); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.bucket_info(1).duration_nanos(), 700); - EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); + EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); } } diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp index 3b25694b6517..024fa3e23180 100644 --- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp @@ -315,9 +315,9 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3) android::util::WAKELOCK_STATE_CHANGED, 111); // The last wakelock holding spans 4 buckets. EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 3 * bucketSizeNs); - EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_nanos(), + EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + 5 * bucketSizeNs); - EXPECT_EQ((unsigned long long)data.bucket_info(1).end_bucket_nanos(), + EXPECT_EQ((unsigned long long)data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 6 * bucketSizeNs); } diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp index a1343002405b..bd114439b83c 100644 --- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp +++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp @@ -225,7 +225,7 @@ TEST(StatsdStatsTest, TestAtomLog) { bool dropboxAtomGood = false; for (const auto& atomStats : report.atom_stats()) { - if (atomStats.tag() == android::util::SENSOR_STATE_CHANGED && atomStats.count() == 2) { + if (atomStats.tag() == android::util::SENSOR_STATE_CHANGED && atomStats.count() == 3) { sensorAtomGood = true; } if (atomStats.tag() == android::util::DROPBOX_ERROR_CHANGED && atomStats.count() == 1) { diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp index 1e71b73ca9fa..d9dbf1d7cadc 100644 --- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp @@ -48,7 +48,9 @@ TEST(CountMetricProducerTest, TestNonDimensionalEvents) { metric.set_bucket(ONE_MINUTE); LogEvent event1(tagId, bucketStartTimeNs + 1); + event1.init(); LogEvent event2(tagId, bucketStartTimeNs + 2); + event2.init(); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); @@ -76,6 +78,8 @@ TEST(CountMetricProducerTest, TestNonDimensionalEvents) { // 1 matched event happens in bucket 2. LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 2); + event3.init(); + countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3); countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1); EXPECT_EQ(1UL, countProducer.mPastBuckets.size()); @@ -106,7 +110,10 @@ TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) { metric.set_condition(StringToId("SCREEN_ON")); LogEvent event1(1, bucketStartTimeNs + 1); + event1.init(); + LogEvent event2(1, bucketStartTimeNs + 10); + event2.init(); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); @@ -326,12 +333,19 @@ TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) { int tagId = 1; LogEvent event1(tagId, bucketStartTimeNs + 1); + event1.init(); LogEvent event2(tagId, bucketStartTimeNs + 2); + event2.init(); LogEvent event3(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1); + event3.init(); LogEvent event4(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1); + event4.init(); LogEvent event5(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2); + event5.init(); LogEvent event6(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3); + event6.init(); LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC); + event7.init(); // Two events in bucket #0. countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1); @@ -355,13 +369,13 @@ TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) { EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second); // Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), - event5.GetTimestampNs() / NS_PER_SEC + refPeriodSec); + event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec); countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7); EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size()); EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second); EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), - event7.GetTimestampNs() / NS_PER_SEC + refPeriodSec); + event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec); } } // namespace statsd diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp index 23e15f78a96c..57e2794c0eea 100644 --- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp @@ -51,7 +51,9 @@ TEST(DurationMetricTrackerTest, TestNoCondition) { int tagId = 1; LogEvent event1(tagId, bucketStartTimeNs + 1); + event1.init(); LogEvent event2(tagId, bucketStartTimeNs + bucketSizeNs + 2); + event2.init(); FieldMatcher dimensions; DurationMetricProducer durationProducer( @@ -86,9 +88,13 @@ TEST(DurationMetricTrackerTest, TestNonSlicedCondition) { int tagId = 1; LogEvent event1(tagId, bucketStartTimeNs + 1); + event1.init(); LogEvent event2(tagId, bucketStartTimeNs + 2); + event2.init(); LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1); + event3.init(); LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3); + event4.init(); FieldMatcher dimensions; DurationMetricProducer durationProducer( @@ -144,7 +150,9 @@ TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) { kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs); - durationProducer.onMatchedLogEvent(1 /* start index*/, LogEvent(tagId, startTimeNs)); + LogEvent start_event(tagId, startTimeNs); + start_event.init(); + durationProducer.onMatchedLogEvent(1 /* start index*/, start_event); EXPECT_EQ(0UL, durationProducer.mPastBuckets.size()); EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs); @@ -158,7 +166,9 @@ TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) { EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs); // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket. - durationProducer.onMatchedLogEvent(2 /* stop index*/, LogEvent(tagId, endTimeNs)); + LogEvent end_event(tagId, endTimeNs); + end_event.init(); + durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event); buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY]; EXPECT_EQ(3UL, buckets.size()); EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketStartNs); @@ -194,7 +204,9 @@ TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket) { kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs); - durationProducer.onMatchedLogEvent(1 /* start index*/, LogEvent(tagId, startTimeNs)); + LogEvent start_event(tagId, startTimeNs); + start_event.init(); + durationProducer.onMatchedLogEvent(1 /* start index*/, start_event); EXPECT_EQ(0UL, durationProducer.mPastBuckets.size()); EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs); @@ -211,7 +223,9 @@ TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket) { EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs); // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket. - durationProducer.onMatchedLogEvent(2 /* stop index*/, LogEvent(tagId, endTimeNs)); + LogEvent end_event(tagId, endTimeNs); + end_event.init(); + durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event); buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY]; EXPECT_EQ(3UL, buckets.size()); EXPECT_EQ(eventUpgradeTimeNs, buckets[2].mBucketStartNs); @@ -245,10 +259,14 @@ TEST(DurationMetricTrackerTest, TestSumDurationAnomalyWithUpgrade) { sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert); EXPECT_TRUE(anomalyTracker != nullptr); - durationProducer.onMatchedLogEvent(1 /* start index*/, LogEvent(tagId, startTimeNs)); + LogEvent start_event(tagId, startTimeNs); + start_event.init(); + durationProducer.onMatchedLogEvent(1 /* start index*/, start_event); durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1); // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket. - durationProducer.onMatchedLogEvent(2 /* stop index*/, LogEvent(tagId, endTimeNs)); + LogEvent end_event(tagId, endTimeNs); + end_event.init(); + durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event); EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs, (uint64_t)anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY)); @@ -276,7 +294,9 @@ TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) { kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs); - durationProducer.onMatchedLogEvent(1 /* start index*/, LogEvent(tagId, startTimeNs)); + LogEvent start_event(tagId, startTimeNs); + start_event.init(); + durationProducer.onMatchedLogEvent(1 /* start index*/, start_event); EXPECT_EQ(0UL, durationProducer.mPastBuckets.size()); EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs); @@ -285,7 +305,9 @@ TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) { EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs); // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket. - durationProducer.onMatchedLogEvent(2 /* stop index*/, LogEvent(tagId, endTimeNs)); + LogEvent end_event(tagId, endTimeNs); + end_event.init(); + durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event); EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); durationProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1); @@ -319,7 +341,9 @@ TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) { kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs); - durationProducer.onMatchedLogEvent(1 /* start index*/, LogEvent(tagId, startTimeNs)); + LogEvent start_event(tagId, startTimeNs); + start_event.init(); + durationProducer.onMatchedLogEvent(1 /* start index*/, start_event); EXPECT_EQ(0UL, durationProducer.mPastBuckets.size()); EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs); @@ -328,7 +352,9 @@ TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) { EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs); // Stop occurs in the same partial bucket as created for the app upgrade. - durationProducer.onMatchedLogEvent(2 /* stop index*/, LogEvent(tagId, endTimeNs)); + LogEvent end_event(tagId, endTimeNs); + end_event.init(); + durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event); EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs); diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index 26f7c2669f15..8b4273bc7929 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -387,7 +387,7 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) { .mFields->begin() ->mValue.int_value); EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), - event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec); + event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec); std::shared_ptr<LogEvent> event3 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10); @@ -402,7 +402,7 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) { .mFields->begin() ->mValue.int_value); EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), - event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec); + event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec); // The event4 does not have the gauge field. Thus the current bucket value is 0. std::shared_ptr<LogEvent> event4 = diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp index 293b1a872a5a..cb731c555e90 100644 --- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp +++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp @@ -59,7 +59,6 @@ TEST(OringDurationTrackerTest, TestDurationOverlap) { uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; uint64_t bucketStartTimeNs = 10000000000; - uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; uint64_t bucketNum = 0; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; uint64_t durationTimeNs = 2 * 1000; @@ -95,7 +94,6 @@ TEST(OringDurationTrackerTest, TestDurationNested) { uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; uint64_t bucketStartTimeNs = 10000000000; - uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; uint64_t bucketNum = 0; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; @@ -129,7 +127,6 @@ TEST(OringDurationTrackerTest, TestStopAll) { uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; uint64_t bucketStartTimeNs = 10000000000; - uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; uint64_t bucketNum = 0; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; @@ -162,7 +159,6 @@ TEST(OringDurationTrackerTest, TestCrossBucketBoundary) { uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; uint64_t bucketStartTimeNs = 10000000000; - uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; uint64_t bucketNum = 0; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; uint64_t durationTimeNs = 2 * 1000; @@ -210,7 +206,6 @@ TEST(OringDurationTrackerTest, TestDurationConditionChange) { uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; uint64_t bucketStartTimeNs = 10000000000; - uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; uint64_t bucketNum = 0; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; uint64_t durationTimeNs = 2 * 1000; @@ -253,7 +248,6 @@ TEST(OringDurationTrackerTest, TestDurationConditionChange2) { uint64_t bucketStartTimeNs = 10000000000; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; - uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; uint64_t bucketNum = 0; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; uint64_t durationTimeNs = 2 * 1000; @@ -296,7 +290,6 @@ TEST(OringDurationTrackerTest, TestDurationConditionChangeNested) { uint64_t bucketStartTimeNs = 10000000000; uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL; - uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; uint64_t bucketNum = 0; uint64_t eventStartTimeNs = bucketStartTimeNs + 1; @@ -338,7 +331,6 @@ TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); uint64_t bucketStartTimeNs = 10 * NS_PER_SEC; - uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; uint64_t bucketNum = 0; uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1; @@ -408,7 +400,6 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); uint64_t bucketStartTimeNs = 10 * NS_PER_SEC; - uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs; uint64_t bucketNum = 0; uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1; @@ -421,15 +412,15 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm) { tracker.noteStop(kEventKey1, eventStartTimeNs + 10, false); EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U); EXPECT_TRUE(tracker.mStarted.empty()); - EXPECT_EQ(10LL, tracker.mDuration); + EXPECT_EQ(10LL, tracker.mDuration); // 10ns EXPECT_EQ(0u, tracker.mStarted.size()); tracker.noteStart(kEventKey1, true, eventStartTimeNs + 20, ConditionKey()); EXPECT_EQ(1u, anomalyTracker->mAlarms.size()); - EXPECT_EQ((long long)(51ULL * NS_PER_SEC), + EXPECT_EQ((long long)(52ULL * NS_PER_SEC), // (10s + 1s + 1ns + 20ns) - 10ns + 40s, rounded up (long long)(anomalyTracker->mAlarms.begin()->second->timestampSec * NS_PER_SEC)); - // The alarm is set to fire at 51s, and when it does, an anomaly would be declared. However, + // The alarm is set to fire at 52s, and when it does, an anomaly would be declared. However, // because this is a unit test, the alarm won't actually fire at all. Since the alarm fails // to fire in time, the anomaly is instead caught when noteStop is called, at around 71s. tracker.flushIfNeeded(eventStartTimeNs + 2 * bucketSizeNs + 25, &buckets); @@ -460,7 +451,6 @@ TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm) { ConditionKey conkey; conkey[StringToId("APP_BACKGROUND")] = kConditionKey1; uint64_t bucketStartTimeNs = 10 * NS_PER_SEC; - uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1; uint64_t bucketSizeNs = 30 * NS_PER_SEC; sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey); diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index 325a372d8056..6e66c6e8dcb6 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -406,16 +406,16 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) { valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4); // Anomaly at event 4 since Value sum == 131 > 130! EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), - event4->GetTimestampNs() / NS_PER_SEC + refPeriodSec); + event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec); valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5); // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4. EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), - event4->GetTimestampNs() / NS_PER_SEC + refPeriodSec); + event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec); valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6); // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period. EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), - event6->GetTimestampNs() / NS_PER_SEC + refPeriodSec); + event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec); } } // namespace statsd diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp index d3a89617e921..b7acef75fafb 100644 --- a/cmds/statsd/tests/statsd_test_util.cpp +++ b/cmds/statsd/tests/statsd_test_util.cpp @@ -406,7 +406,7 @@ AttributionNode CreateAttribution(const int& uid, const string& tag) { void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events) { std::sort(events->begin(), events->end(), [](const std::unique_ptr<LogEvent>& a, const std::unique_ptr<LogEvent>& b) { - return a->GetTimestampNs() < b->GetTimestampNs(); + return a->GetElapsedTimestampNs() < b->GetElapsedTimestampNs(); }); } 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 03e5fef5d717..b6b16e40a4b2 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,9 +32,9 @@ 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())). + sb.append("Last report time:").append(getDateStr(report.getLastReportElapsedNanos())). append("\n"); - sb.append("Current report time:").append(getDateStr(report.getCurrentReportNanos())). + sb.append("Current report time:").append(getDateStr(report.getCurrentReportElapsedNanos())). append("\n"); for (StatsLog.StatsLogReport log : report.getMetricsList()) { sb.append("\n\n"); @@ -109,8 +109,8 @@ public class DisplayProtoUtils { } for (StatsLog.DurationBucketInfo info : duration.getBucketInfoList()) { - sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-") - .append(getDateStr(info.getEndBucketNanos())).append("] -> ") + sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-") + .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ") .append(info.getDurationNanos()).append(" ns\n"); } } @@ -121,7 +121,7 @@ public class DisplayProtoUtils { StatsLog.StatsLogReport.EventMetricDataWrapper eventMetricDataWrapper = log.getEventMetrics(); for (StatsLog.EventMetricData event : eventMetricDataWrapper.getDataList()) { - sb.append(getDateStr(event.getTimestampNanos())).append(": "); + sb.append(getDateStr(event.getElapsedTimestampNanos())).append(": "); sb.append(event.getAtom().getPushedCase().toString()).append("\n"); } } @@ -141,8 +141,8 @@ public class DisplayProtoUtils { } for (StatsLog.CountBucketInfo info : count.getBucketInfoList()) { - sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-") - .append(getDateStr(info.getEndBucketNanos())).append("] -> ") + sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-") + .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ") .append(info.getCount()).append("\n"); } } 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 87b82c261bf1..d55f3f31fd9f 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,9 +36,9 @@ 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())). + sb.append("Last report time:").append(getDateStr(report.getLastReportElapsedNanos())). append("\n"); - sb.append("Current report time:").append(getDateStr(report.getCurrentReportNanos())). + sb.append("Current report time:").append(getDateStr(report.getCurrentReportElapsedNanos())). append("\n"); for (StatsLog.StatsLogReport log : report.getMetricsList()) { numMetrics++; @@ -120,8 +120,8 @@ public class DisplayProtoUtils { } for (StatsLog.DurationBucketInfo info : duration.getBucketInfoList()) { - sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-") - .append(getDateStr(info.getEndBucketNanos())).append("] -> ") + sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-") + .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ") .append(info.getDurationNanos()).append(" ns\n"); } } @@ -132,7 +132,7 @@ public class DisplayProtoUtils { StatsLog.StatsLogReport.EventMetricDataWrapper eventMetricDataWrapper = log.getEventMetrics(); for (StatsLog.EventMetricData event : eventMetricDataWrapper.getDataList()) { - sb.append(getDateStr(event.getTimestampNanos())).append(": "); + sb.append(getDateStr(event.getElapsedTimestampNanos())).append(": "); sb.append(event.getAtom().getPushedCase().toString()).append("\n"); } } @@ -152,8 +152,8 @@ public class DisplayProtoUtils { } for (StatsLog.CountBucketInfo info : count.getBucketInfoList()) { - sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-") - .append(getDateStr(info.getEndBucketNanos())).append("] -> ") + sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-") + .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ") .append(info.getCount()).append("\n"); } } diff --git a/core/java/Android.bp b/core/java/Android.bp index f7c5c57a07e4..fb27f74211fb 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -7,33 +7,3 @@ filegroup { name: "IDropBoxManagerService.aidl", srcs: ["com/android/internal/os/IDropBoxManagerService.aidl"], } - -// only used by key_store_service -cc_library_shared { - name: "libkeystore_aidl", - srcs: ["android/security/IKeystoreService.aidl", - "android/security/IConfirmationPromptCallback.aidl"], - aidl: { - export_aidl_headers: true, - include_dirs: [ - "frameworks/base/core/java/", - "system/security/keystore/", - ], - }, - shared_libs: [ - "libbinder", - "libcutils", - "libhardware", - "libhidlbase", - "libhidltransport", - "libhwbinder", - "liblog", - "libkeystore_parcelables", - "libselinux", - "libutils", - ], - export_shared_lib_headers: [ - "libbinder", - "libkeystore_parcelables", - ], -} diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 0bc510a13ba6..bcd88fee6720 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1733,7 +1733,7 @@ public class Activity extends ContextThemeWrapper * * <p>This callback and {@link #onUserInteraction} are intended to help * activities manage status bar notifications intelligently; specifically, - * for helping activities determine the proper time to cancel a notfication. + * for helping activities determine the proper time to cancel a notification. * * @see #onUserInteraction() */ @@ -1741,32 +1741,16 @@ public class Activity extends ContextThemeWrapper } /** - * Generate a new thumbnail for this activity. This method is called before - * pausing the activity, and should draw into <var>outBitmap</var> the - * imagery for the desired thumbnail in the dimensions of that bitmap. It - * can use the given <var>canvas</var>, which is configured to draw into the - * bitmap, for rendering if desired. - * - * <p>The default implementation returns fails and does not draw a thumbnail; - * this will result in the platform creating its own thumbnail if needed. - * - * @param outBitmap The bitmap to contain the thumbnail. - * @param canvas Can be used to render into the bitmap. - * - * @return Return true if you have drawn into the bitmap; otherwise after - * you return it will be filled with a default thumbnail. - * - * @see #onCreateDescription - * @see #onSaveInstanceState - * @see #onPause + * @deprecated Method doesn't do anything and will be removed in the future. */ + @Deprecated public boolean onCreateThumbnail(Bitmap outBitmap, Canvas canvas) { return false; } /** * Generate a new description for this activity. This method is called - * before pausing the activity and can, if desired, return some textual + * before stopping the activity and can, if desired, return some textual * description of its current state to be displayed to the user. * * <p>The default implementation returns null, which will cause you to @@ -1777,9 +1761,8 @@ public class Activity extends ContextThemeWrapper * @return A description of what the user is doing. It should be short and * sweet (only a few words). * - * @see #onCreateThumbnail * @see #onSaveInstanceState - * @see #onPause + * @see #onStop */ @Nullable public CharSequence onCreateDescription() { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 5a6331919d76..a69b0ee70f4d 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3904,62 +3904,6 @@ public final class ActivityThread extends ClientTransactionHandler { } } - private int mThumbnailWidth = -1; - private int mThumbnailHeight = -1; - private Bitmap mAvailThumbnailBitmap = null; - private Canvas mThumbnailCanvas = null; - - private Bitmap createThumbnailBitmap(ActivityClientRecord r) { - Bitmap thumbnail = mAvailThumbnailBitmap; - try { - if (thumbnail == null) { - int w = mThumbnailWidth; - int h; - if (w < 0) { - Resources res = r.activity.getResources(); - int wId = com.android.internal.R.dimen.thumbnail_width; - int hId = com.android.internal.R.dimen.thumbnail_height; - mThumbnailWidth = w = res.getDimensionPixelSize(wId); - mThumbnailHeight = h = res.getDimensionPixelSize(hId); - } else { - h = mThumbnailHeight; - } - - // On platforms where we don't want thumbnails, set dims to (0,0) - if ((w > 0) && (h > 0)) { - thumbnail = Bitmap.createBitmap(r.activity.getResources().getDisplayMetrics(), - w, h, THUMBNAIL_FORMAT); - thumbnail.eraseColor(0); - } - } - - if (thumbnail != null) { - Canvas cv = mThumbnailCanvas; - if (cv == null) { - mThumbnailCanvas = cv = new Canvas(); - } - - cv.setBitmap(thumbnail); - if (!r.activity.onCreateThumbnail(thumbnail, cv)) { - mAvailThumbnailBitmap = thumbnail; - thumbnail = null; - } - cv.setBitmap(null); - } - - } catch (Exception e) { - if (!mInstrumentation.onException(r.activity, e)) { - throw new RuntimeException( - "Unable to create thumbnail of " - + r.intent.getComponent().toShortString() - + ": " + e.toString(), e); - } - thumbnail = null; - } - - return thumbnail; - } - @Override public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport, PendingTransactionActions pendingActions) { diff --git a/core/java/android/app/admin/FreezeInterval.java b/core/java/android/app/admin/FreezeInterval.java index 7acdfc8fe100..de5e21ac75c4 100644 --- a/core/java/android/app/admin/FreezeInterval.java +++ b/core/java/android/app/admin/FreezeInterval.java @@ -84,6 +84,10 @@ public class FreezeInterval { } } + boolean after(LocalDate localDate) { + return mStartDay > dayOfYearDisregardLeapYear(localDate); + } + /** * Instantiate the current interval to real calendar dates, given a calendar date * {@code now}. If the interval contains now, the returned calendar dates should be the @@ -161,7 +165,7 @@ public class FreezeInterval { * 3. At most one wrapped Interval remains, and it will be at the end of the list * @hide */ - private static List<FreezeInterval> canonicalizeIntervals(List<FreezeInterval> intervals) { + protected static List<FreezeInterval> canonicalizeIntervals(List<FreezeInterval> intervals) { boolean[] taken = new boolean[DAYS_IN_YEAR]; // First convert the intervals into flat array for (FreezeInterval interval : intervals) { diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java index 202b89496007..69ec26c275a2 100644 --- a/core/java/android/app/admin/SecurityLog.java +++ b/core/java/android/app/admin/SecurityLog.java @@ -78,6 +78,8 @@ public class SecurityLog { TAG_CERT_AUTHORITY_INSTALLED, TAG_CERT_AUTHORITY_REMOVED, TAG_CRYPTO_SELF_TEST_COMPLETED, + TAG_KEY_INTEGRITY_VIOLATION, + TAG_CERT_VALIDATION_FAILURE, }) public @interface SecurityLogTag {} @@ -409,6 +411,23 @@ public class SecurityLog { SecurityLogTags.SECURITY_CRYPTO_SELF_TEST_COMPLETED; /** + * Indicates a failed cryptographic key integrity check. The log entry contains the following + * information about the event, encapsulated in an {@link Object} array and accessible via + * {@link SecurityEvent#getData()}: + * <li> [0] alias of the key ({@code String}) + * <li> [1] owner application uid ({@code Integer}). + */ + public static final int TAG_KEY_INTEGRITY_VIOLATION = + SecurityLogTags.SECURITY_KEY_INTEGRITY_VIOLATION; + + /** + * Indicates a failure to validate X.509v3 certificate. The log entry contains a {@code String} + * payload indicating the failure reason, accessible via {@link SecurityEvent#getData()}. + */ + public static final int TAG_CERT_VALIDATION_FAILURE = + SecurityLogTags.SECURITY_CERT_VALIDATION_FAILURE; + + /** * Event severity level indicating that the event corresponds to normal workflow. */ public static final int LEVEL_INFO = 1; @@ -548,7 +567,10 @@ public class SecurityLog { return getSuccess() ? LEVEL_INFO : LEVEL_WARNING; case TAG_LOG_BUFFER_SIZE_CRITICAL: case TAG_WIPE_FAILURE: + case TAG_KEY_INTEGRITY_VIOLATION: return LEVEL_ERROR; + case TAG_CERT_VALIDATION_FAILURE: + return LEVEL_WARNING; default: return LEVEL_INFO; } diff --git a/core/java/android/app/admin/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags index b64b7e3e4432..fe2519d2bdf1 100644 --- a/core/java/android/app/admin/SecurityLogTags.logtags +++ b/core/java/android/app/admin/SecurityLogTags.logtags @@ -35,4 +35,6 @@ option java_package android.app.admin 210028 security_user_restriction_removed (package|3),(admin_user|1),(restriction|3) 210029 security_cert_authority_installed (success|1),(subject|3) 210030 security_cert_authority_removed (success|1),(subject|3) -210031 security_crypto_self_test_completed (success|1)
\ No newline at end of file +210031 security_crypto_self_test_completed (success|1) +210032 security_key_integrity_violation (key_id|3),(uid|1) +210033 security_cert_validation_failure (reason|3) diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java index 05d3fd9c632c..47b3a81d0174 100644 --- a/core/java/android/app/admin/SystemUpdatePolicy.java +++ b/core/java/android/app/admin/SystemUpdatePolicy.java @@ -21,6 +21,7 @@ import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.TEXT; import android.annotation.IntDef; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; @@ -33,9 +34,15 @@ import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.time.Instant; import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -103,6 +110,19 @@ public class SystemUpdatePolicy implements Parcelable { */ public static final int TYPE_POSTPONE = 3; + /** + * Incoming system updates (including security updates) should be blocked. This flag is not + * exposed to third-party apps (and any attempt to set it will raise exceptions). This is used + * to represent the current installation option type to the privileged system update clients, + * for example to indicate OTA freeze is currently in place or when system is outside a daily + * maintenance window. + * + * @see InstallationOption + * @hide + */ + @SystemApi + public static final int TYPE_PAUSE = 4; + private static final String KEY_POLICY_TYPE = "policy_type"; private static final String KEY_INSTALL_WINDOW_START = "install_window_start"; private static final String KEY_INSTALL_WINDOW_END = "install_window_end"; @@ -460,6 +480,30 @@ public class SystemUpdatePolicy implements Parcelable { return null; } + /** + * Returns time (in milliseconds) until the start of the next freeze period, assuming now + * is not within a freeze period. + */ + private long timeUntilNextFreezePeriod(long now) { + List<FreezeInterval> sortedPeriods = FreezeInterval.canonicalizeIntervals(mFreezePeriods); + LocalDate nowDate = millisToDate(now); + LocalDate nextFreezeStart = null; + for (FreezeInterval interval : sortedPeriods) { + if (interval.after(nowDate)) { + nextFreezeStart = interval.toCurrentOrFutureRealDates(nowDate).first; + break; + } else if (interval.contains(nowDate)) { + throw new IllegalArgumentException("Given date is inside a freeze period"); + } + } + if (nextFreezeStart == null) { + // If no interval is after now, then it must be the one that starts at the beginning + // of next year + nextFreezeStart = sortedPeriods.get(0).toCurrentOrFutureRealDates(nowDate).first; + } + return dateToMillis(nextFreezeStart) - now; + } + /** @hide */ public void validateFreezePeriods() { FreezeInterval.validatePeriods(mFreezePeriods); @@ -472,6 +516,134 @@ public class SystemUpdatePolicy implements Parcelable { prevPeriodEnd, now); } + /** + * An installation option represents how system update clients should act on incoming system + * updates and how long this action is valid for, given the current system update policy. Its + * action could be one of the following + * <ul> + * <li> {@code TYPE_INSTALL_AUTOMATIC} system updates should be installed immedately and without + * user intervention as soon as they become available. + * <li> {@code TYPE_POSTPONE} system updates should be postponed for a maximum of 30 days + * <li> {@code TYPE_PAUSE} system updates should be postponed indefinitely until further notice + * </ul> + * + * The effective time measures how long this installation option is valid for from the queried + * time, in milliseconds. + * + * This is an internal API for system update clients. + * @hide + */ + @SystemApi + public static class InstallationOption { + private final int mType; + private long mEffectiveTime; + + InstallationOption(int type, long effectiveTime) { + this.mType = type; + this.mEffectiveTime = effectiveTime; + } + + public int getType() { + return mType; + } + + public long getEffectiveTime() { + return mEffectiveTime; + } + + /** @hide */ + protected void limitEffectiveTime(long otherTime) { + mEffectiveTime = Long.min(mEffectiveTime, otherTime); + } + } + + /** + * Returns the installation option at the specified time, under the current + * {@code SystemUpdatePolicy} object. This is a convenience method for system update clients + * so they can instantiate this policy at any given time and find out what to do with incoming + * system updates, without the need of examining the overall policy structure. + * + * Normally the system update clients will query the current installation option by calling this + * method with the current timestamp, and act on the returned option until its effective time + * lapses. It can then query the latest option using a new timestamp. It should also listen + * for {@code DevicePolicyManager#ACTION_SYSTEM_UPDATE_POLICY_CHANGED} broadcast, in case the + * whole policy is updated. + * + * @param when At what time the intallation option is being queried, specified in number of + milliseonds since the epoch. + * @see InstallationOption + * @hide + */ + @SystemApi + public InstallationOption getInstallationOptionAt(long when) { + LocalDate whenDate = millisToDate(when); + Pair<LocalDate, LocalDate> current = getCurrentFreezePeriod(whenDate); + if (current != null) { + return new InstallationOption(TYPE_PAUSE, + dateToMillis(roundUpLeapDay(current.second).plusDays(1)) - when); + } + // We are not within a freeze period, query the underlying policy. + // But also consider the start of the next freeze period, which might + // reduce the effective time of the current installation option + InstallationOption option = getInstallationOptionRegardlessFreezeAt(when); + if (mFreezePeriods.size() > 0) { + option.limitEffectiveTime(timeUntilNextFreezePeriod(when)); + } + return option; + } + + private InstallationOption getInstallationOptionRegardlessFreezeAt(long when) { + if (mPolicyType == TYPE_INSTALL_AUTOMATIC || mPolicyType == TYPE_POSTPONE) { + return new InstallationOption(mPolicyType, Long.MAX_VALUE); + } else if (mPolicyType == TYPE_INSTALL_WINDOWED) { + Calendar query = Calendar.getInstance(); + query.setTimeInMillis(when); + // Calculate the number of milliseconds since midnight of the time specified by when + long whenMillis = TimeUnit.HOURS.toMillis(query.get(Calendar.HOUR_OF_DAY)) + + TimeUnit.MINUTES.toMillis(query.get(Calendar.MINUTE)) + + TimeUnit.SECONDS.toMillis(query.get(Calendar.SECOND)) + + query.get(Calendar.MILLISECOND); + long windowStartMillis = TimeUnit.MINUTES.toMillis(mMaintenanceWindowStart); + long windowEndMillis = TimeUnit.MINUTES.toMillis(mMaintenanceWindowEnd); + final long dayInMillis = TimeUnit.DAYS.toMillis(1); + + if ((windowStartMillis <= whenMillis && whenMillis <= windowEndMillis) + || ((windowStartMillis > windowEndMillis) + && (windowStartMillis <= whenMillis || whenMillis <= windowEndMillis))) { + return new InstallationOption(TYPE_INSTALL_AUTOMATIC, + (windowEndMillis - whenMillis + dayInMillis) % dayInMillis); + } else { + return new InstallationOption(TYPE_PAUSE, + (windowStartMillis - whenMillis + dayInMillis) % dayInMillis); + } + } else { + throw new RuntimeException("Unknown policy type"); + } + } + + private static LocalDate roundUpLeapDay(LocalDate date) { + if (date.isLeapYear() && date.getMonthValue() == 2 && date.getDayOfMonth() == 28) { + return date.plusDays(1); + } else { + return date; + } + } + + /** Convert a timestamp since epoch to a LocalDate using default timezone, truncating + * the hour/min/seconds part. + */ + private static LocalDate millisToDate(long when) { + return Instant.ofEpochMilli(when).atZone(ZoneId.systemDefault()).toLocalDate(); + } + + /** + * Returns the timestamp since epoch of a LocalDate, assuming the time is 00:00:00. + */ + private static long dateToMillis(LocalDate when) { + return LocalDateTime.of(when, LocalTime.MIN).atZone(ZoneId.systemDefault()).toInstant() + .toEpochMilli(); + } + @Override public String toString() { return String.format("SystemUpdatePolicy (type: %d, windowStart: %d, windowEnd: %d, " @@ -480,11 +652,13 @@ public class SystemUpdatePolicy implements Parcelable { mFreezePeriods.stream().map(n -> n.toString()).collect(Collectors.joining(","))); } + @SystemApi @Override public int describeContents() { return 0; } + @SystemApi @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mPolicyType); @@ -499,6 +673,7 @@ public class SystemUpdatePolicy implements Parcelable { } } + @SystemApi public static final Parcelable.Creator<SystemUpdatePolicy> CREATOR = new Parcelable.Creator<SystemUpdatePolicy>() { diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index aa8faf8d4474..07a991188a49 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2070,6 +2070,15 @@ public abstract class PackageManager { "android.hardware.sensor.hifi_sensors"; /** + * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: + * The device supports a hardware mechanism for invoking an assist gesture. + * @see android.provider.Settings.Secure#ASSIST_GESTURE_ENABLED + * @hide + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_ASSIST_GESTURE = "android.hardware.sensor.assist"; + + /** * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: The device has a telephony radio with data * communication support. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index fef6495e5c88..1223271ad4c7 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11391,6 +11391,14 @@ public final class Settings { "autofill_compat_allowed_packages"; /** + * Exemptions to the hidden API blacklist. + * + * @hide + */ + public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS = + "hidden_api_blacklist_exemptions"; + + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. * @@ -12134,6 +12142,12 @@ public final class Settings { * @hide */ public static final String SHOW_MUTE_IN_CRASH_DIALOG = "show_mute_in_crash_dialog"; + + /** + * If nonzero, will show the zen upgrade notification when the user toggles DND on/off. + * @hide + */ + public static final String SHOW_ZEN_UPGRADE_NOTIFICATION = "show_zen_upgrade_notification"; } /** diff --git a/core/java/android/security/IConfirmationPromptCallback.aidl b/core/java/android/security/IConfirmationPromptCallback.aidl deleted file mode 100644 index 96a1a04828b5..000000000000 --- a/core/java/android/security/IConfirmationPromptCallback.aidl +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2017, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security; - -/** - * This must be kept manually in sync with system/security/keystore until AIDL - * can generate both Java and C++ bindings. - * - * @hide - */ -interface IConfirmationPromptCallback { - oneway void onConfirmationPromptCompleted(in int result, in byte[] dataThatWasConfirmed); -} diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl deleted file mode 100644 index 738eb6865230..000000000000 --- a/core/java/android/security/IKeystoreService.aidl +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (c) 2015, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security; - -import android.security.keymaster.ExportResult; -import android.security.keymaster.KeyCharacteristics; -import android.security.keymaster.KeymasterArguments; -import android.security.keymaster.KeymasterCertificateChain; -import android.security.keymaster.KeymasterBlob; -import android.security.keymaster.OperationResult; -import android.security.KeystoreArguments; - -/** - * This must be kept manually in sync with system/security/keystore until AIDL - * can generate both Java and C++ bindings. - * - * @hide - */ -interface IKeystoreService { - int getState(int userId); - byte[] get(String name, int uid); - int insert(String name, in byte[] item, int uid, int flags); - int del(String name, int uid); - int exist(String name, int uid); - String[] list(String namePrefix, int uid); - int reset(); - int onUserPasswordChanged(int userId, String newPassword); - int lock(int userId); - int unlock(int userId, String userPassword); - int isEmpty(int userId); - int generate(String name, int uid, int keyType, int keySize, int flags, - in KeystoreArguments args); - int import_key(String name, in byte[] data, int uid, int flags); - byte[] sign(String name, in byte[] data); - int verify(String name, in byte[] data, in byte[] signature); - byte[] get_pubkey(String name); - String grant(String name, int granteeUid); - int ungrant(String name, int granteeUid); - long getmtime(String name, int uid); - int is_hardware_backed(String string); - int clear_uid(long uid); - - // Keymaster 0.4 methods - int addRngEntropy(in byte[] data, int flags); - int generateKey(String alias, in KeymasterArguments arguments, in byte[] entropy, int uid, - int flags, out KeyCharacteristics characteristics); - int getKeyCharacteristics(String alias, in KeymasterBlob clientId, in KeymasterBlob appId, - int uid, out KeyCharacteristics characteristics); - int importKey(String alias, in KeymasterArguments arguments, int format, - in byte[] keyData, int uid, int flags, out KeyCharacteristics characteristics); - ExportResult exportKey(String alias, int format, in KeymasterBlob clientId, - in KeymasterBlob appId, int uid); - OperationResult begin(IBinder appToken, String alias, int purpose, boolean pruneable, - in KeymasterArguments params, in byte[] entropy, int uid); - OperationResult update(IBinder token, in KeymasterArguments params, in byte[] input); - OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature, - in byte[] entropy); - int abort(IBinder handle); - boolean isOperationAuthorized(IBinder token); - int addAuthToken(in byte[] authToken); - int onUserAdded(int userId, int parentId); - int onUserRemoved(int userId); - int attestKey(String alias, in KeymasterArguments params, out KeymasterCertificateChain chain); - int attestDeviceIds(in KeymasterArguments params, out KeymasterCertificateChain chain); - int onDeviceOffBody(); - int importWrappedKey(in String wrappedKeyAlias, in byte[] wrappedKey, - in String wrappingKeyAlias, in byte[] maskingKey, in KeymasterArguments arguments, - in long rootSid, in long fingerprintSid, - out KeyCharacteristics characteristics); - int presentConfirmationPrompt(IBinder listener, String promptText, in byte[] extraData, - in String locale, in int uiOptionsAsFlags); - int cancelConfirmationPrompt(IBinder listener); -} diff --git a/core/java/android/security/KeystoreArguments.aidl b/core/java/android/security/KeystoreArguments.aidl deleted file mode 100644 index dc8ed50182ed..000000000000 --- a/core/java/android/security/KeystoreArguments.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2015, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security; - -/* @hide */ -parcelable KeystoreArguments cpp_header "keystore/KeystoreArguments.h"; diff --git a/core/java/android/security/keymaster/ExportResult.aidl b/core/java/android/security/keymaster/ExportResult.aidl deleted file mode 100644 index 17486531a3f0..000000000000 --- a/core/java/android/security/keymaster/ExportResult.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security.keymaster; - -/* @hide */ -parcelable ExportResult cpp_header "keystore/ExportResult.h"; diff --git a/core/java/android/security/keymaster/KeyCharacteristics.aidl b/core/java/android/security/keymaster/KeyCharacteristics.aidl deleted file mode 100644 index 32e75ad267b2..000000000000 --- a/core/java/android/security/keymaster/KeyCharacteristics.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security.keymaster; - -/* @hide */ -parcelable KeyCharacteristics cpp_header "keystore/KeyCharacteristics.h"; diff --git a/core/java/android/security/keymaster/KeymasterBlob.aidl b/core/java/android/security/keymaster/KeymasterBlob.aidl deleted file mode 100644 index 5c5db9ec314b..000000000000 --- a/core/java/android/security/keymaster/KeymasterBlob.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security.keymaster; - -/* @hide */ -parcelable KeymasterBlob cpp_header "keystore/KeymasterBlob.h"; diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.aidl b/core/java/android/security/keymaster/KeymasterCertificateChain.aidl deleted file mode 100644 index ddb5cae1a254..000000000000 --- a/core/java/android/security/keymaster/KeymasterCertificateChain.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security.keymaster; - -/* @hide */ -parcelable KeymasterCertificateChain cpp_header "keystore/KeymasterCertificateChain.h"; diff --git a/core/java/android/security/keymaster/OperationResult.aidl b/core/java/android/security/keymaster/OperationResult.aidl deleted file mode 100644 index db689d46521a..000000000000 --- a/core/java/android/security/keymaster/OperationResult.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security.keymaster; - -/* @hide */ -parcelable OperationResult cpp_header "keystore/OperationResult.h"; diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index d66322c3aa89..171d4d938beb 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -94,7 +94,7 @@ public class ZenModeConfig implements Parcelable { private static final boolean DEFAULT_ALLOW_SCREEN_OFF = true; private static final boolean DEFAULT_ALLOW_SCREEN_ON = true; - private static final int XML_VERSION = 2; + public static final int XML_VERSION = 3; public static final String ZEN_TAG = "zen"; private static final String ZEN_ATT_VERSION = "version"; private static final String ZEN_ATT_USER = "user"; @@ -145,6 +145,7 @@ public class ZenModeConfig implements Parcelable { public int user = UserHandle.USER_SYSTEM; public boolean allowWhenScreenOff = DEFAULT_ALLOW_SCREEN_OFF; public boolean allowWhenScreenOn = DEFAULT_ALLOW_SCREEN_ON; + public int version; public ZenRule manualRule; public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>(); @@ -431,6 +432,7 @@ public class ZenModeConfig implements Parcelable { String tag = parser.getName(); if (!ZEN_TAG.equals(tag)) return null; final ZenModeConfig rt = new ZenModeConfig(); + rt.version = safeInt(parser, ZEN_ATT_VERSION, XML_VERSION); rt.user = safeInt(parser, ZEN_ATT_USER, rt.user); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { tag = parser.getName(); diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index bd7f8e5419eb..fc782118ff3e 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -152,6 +152,7 @@ public class SurfaceControl implements Parcelable { private static native void nativeSeverChildren(long transactionObj, long nativeObject); private static native void nativeSetOverrideScalingMode(long transactionObj, long nativeObject, int scalingMode); + private static native void nativeDestroy(long transactionObj, long nativeObject); private static native IBinder nativeGetHandle(long nativeObject); private static native boolean nativeGetTransformToDisplayInverse(long nativeObject); @@ -1570,6 +1571,16 @@ public class SurfaceControl implements Parcelable { return this; } + /** + * Same as {@link #destroy()} except this is invoked in a transaction instead of + * immediately. + */ + public Transaction destroy(SurfaceControl sc) { + sc.checkNotReleased(); + nativeDestroy(mNativeObject, sc.mNativeObject); + return this; + } + public Transaction setDisplaySurface(IBinder displayToken, Surface surface) { if (displayToken == null) { throw new IllegalArgumentException("displayToken must not be null"); diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java index bb9e391ddcb4..7bae28a4e817 100644 --- a/core/java/android/view/WindowInfo.java +++ b/core/java/android/view/WindowInfo.java @@ -21,6 +21,7 @@ import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.util.Pools; +import android.view.accessibility.AccessibilityNodeInfo; import java.util.ArrayList; import java.util.List; @@ -46,7 +47,7 @@ public class WindowInfo implements Parcelable { public final Rect boundsInScreen = new Rect(); public List<IBinder> childTokens; public CharSequence title; - public int accessibilityIdOfAnchor = View.NO_ID; + public long accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID; public boolean inPictureInPicture; private WindowInfo() { @@ -105,7 +106,7 @@ public class WindowInfo implements Parcelable { parcel.writeInt(focused ? 1 : 0); boundsInScreen.writeToParcel(parcel, flags); parcel.writeCharSequence(title); - parcel.writeInt(accessibilityIdOfAnchor); + parcel.writeLong(accessibilityIdOfAnchor); parcel.writeInt(inPictureInPicture ? 1 : 0); if (childTokens != null && !childTokens.isEmpty()) { @@ -142,7 +143,7 @@ public class WindowInfo implements Parcelable { focused = (parcel.readInt() == 1); boundsInScreen.readFromParcel(parcel); title = parcel.readCharSequence(); - accessibilityIdOfAnchor = parcel.readInt(); + accessibilityIdOfAnchor = parcel.readLong(); inPictureInPicture = (parcel.readInt() == 1); final boolean hasChildren = (parcel.readInt() == 1); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 1c5e87197750..c0a966602b0a 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -63,6 +63,7 @@ import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; import android.util.proto.ProtoOutputStream; +import android.view.accessibility.AccessibilityNodeInfo; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -2344,7 +2345,7 @@ public interface WindowManager extends ViewManager { * * @hide */ - public int accessibilityIdOfAnchor = -1; + public long accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID; /** * The window title isn't kept in sync with what is displayed in the title bar, so we @@ -2538,7 +2539,7 @@ public interface WindowManager extends ViewManager { out.writeInt(hasManualSurfaceInsets ? 1 : 0); out.writeInt(preservePreviousSurfaceInsets ? 1 : 0); out.writeInt(needsMenuKey); - out.writeInt(accessibilityIdOfAnchor); + out.writeLong(accessibilityIdOfAnchor); TextUtils.writeToParcel(accessibilityTitle, out, parcelableFlags); out.writeInt(mColorMode); out.writeLong(hideTimeoutMilliseconds); @@ -2594,7 +2595,7 @@ public interface WindowManager extends ViewManager { hasManualSurfaceInsets = in.readInt() != 0; preservePreviousSurfaceInsets = in.readInt() != 0; needsMenuKey = in.readInt(); - accessibilityIdOfAnchor = in.readInt(); + accessibilityIdOfAnchor = in.readLong(); accessibilityTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); mColorMode = in.readInt(); hideTimeoutMilliseconds = in.readLong(); diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java index 4a181b27b2e3..44adbb22eb7e 100644 --- a/core/java/com/android/internal/notification/SystemNotificationChannels.java +++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java @@ -49,6 +49,7 @@ public class SystemNotificationChannels { public static String USB = "USB"; public static String FOREGROUND_SERVICE = "FOREGROUND_SERVICE"; public static String HEAVY_WEIGHT_APP = "HEAVY_WEIGHT_APP"; + public static String SYSTEM_CHANGES = "SYSTEM_CHANGES"; public static void createAll(Context context) { final NotificationManager nm = context.getSystemService(NotificationManager.class); @@ -152,6 +153,11 @@ public class SystemNotificationChannels { .build()); channelsList.add(heavyWeightChannel); + NotificationChannel systemChanges = new NotificationChannel(SYSTEM_CHANGES, + context.getString(R.string.notification_channel_system_changes), + NotificationManager.IMPORTANCE_LOW); + channelsList.add(systemChanges); + nm.createNotificationChannels(channelsList); } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index eb58b0919385..6a56f452f3fe 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -187,7 +187,7 @@ public class BatteryStatsImpl extends BatteryStats { public final AtomicFile mCheckinFile; public final AtomicFile mDailyFile; - static final int MSG_UPDATE_WAKELOCKS = 1; + static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1; static final int MSG_REPORT_POWER_CHANGE = 2; static final int MSG_REPORT_CHARGING = 3; static final long DELAY_UPDATE_WAKELOCKS = 5*1000; @@ -273,10 +273,7 @@ public class BatteryStatsImpl extends BatteryStats { public void handleMessage(Message msg) { BatteryCallback cb = mCallback; switch (msg.what) { - case MSG_UPDATE_WAKELOCKS: - synchronized (BatteryStatsImpl.this) { - updateCpuTimeLocked(); - } + case MSG_REPORT_CPU_UPDATE_NEEDED: if (cb != null) { cb.batteryNeedsCpuUpdate(); } @@ -302,6 +299,10 @@ public class BatteryStatsImpl extends BatteryStats { } } + public void postBatteryNeedsCpuUpdateMsg() { + mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED); + } + /** * Update per-freq cpu times for all the uids in {@link #mPendingUids}. */ @@ -487,6 +488,10 @@ public class BatteryStatsImpl extends BatteryStats { Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff); Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff); Future<?> scheduleCpuSyncDueToSettingChange(); + Future<?> scheduleCpuSyncDueToScreenStateChange(boolean onBattery, + boolean onBatteryScreenOff); + Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis); + void cancelCpuSyncDueToWakelockChange(); } public Handler mHandler; @@ -1453,12 +1458,10 @@ public class BatteryStatsImpl extends BatteryStats { long mCount; long mLoadedCount; long mUnpluggedCount; - long mPluggedCount; LongSamplingCounter(TimeBase timeBase, Parcel in) { mTimeBase = timeBase; - mPluggedCount = in.readLong(); - mCount = mPluggedCount; + mCount = in.readLong(); mLoadedCount = in.readLong(); mUnpluggedCount = in.readLong(); timeBase.add(this); @@ -1477,16 +1480,15 @@ public class BatteryStatsImpl extends BatteryStats { @Override public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { - mUnpluggedCount = mPluggedCount; + mUnpluggedCount = mCount; } @Override public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { - mPluggedCount = mCount; } public long getCountLocked(int which) { - long val = mTimeBase.isRunning() ? mCount : mPluggedCount; + long val = mCount; if (which == STATS_SINCE_UNPLUGGED) { val -= mUnpluggedCount; } else if (which != STATS_SINCE_CHARGED) { @@ -1499,12 +1501,15 @@ public class BatteryStatsImpl extends BatteryStats { public void logState(Printer pw, String prefix) { pw.println(prefix + "mCount=" + mCount + " mLoadedCount=" + mLoadedCount - + " mUnpluggedCount=" + mUnpluggedCount - + " mPluggedCount=" + mPluggedCount); + + " mUnpluggedCount=" + mUnpluggedCount); } void addCountLocked(long count) { - if (mTimeBase.isRunning()) { + addCountLocked(count, mTimeBase.isRunning()); + } + + void addCountLocked(long count, boolean isRunning) { + if (isRunning) { mCount += count; } } @@ -1514,7 +1519,7 @@ public class BatteryStatsImpl extends BatteryStats { */ void reset(boolean detachIfReset) { mCount = 0; - mLoadedCount = mPluggedCount = mUnpluggedCount = 0; + mLoadedCount = mUnpluggedCount = 0; if (detachIfReset) { detach(); } @@ -1531,7 +1536,7 @@ public class BatteryStatsImpl extends BatteryStats { void readSummaryFromParcelLocked(Parcel in) { mLoadedCount = in.readLong(); mCount = mLoadedCount; - mUnpluggedCount = mPluggedCount = mLoadedCount; + mUnpluggedCount = mLoadedCount; } } @@ -3852,9 +3857,6 @@ public class BatteryStatsImpl extends BatteryStats { + Display.stateToString(screenState) + " and battery is " + (unplugged ? "on" : "off")); } - updateCpuTimeLocked(); - mExternalSync.scheduleCopyFromAllUidsCpuTimes(mOnBatteryTimeBase.isRunning(), - mOnBatteryScreenOffTimeBase.isRunning()); mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime); if (updateOnBatteryTimeBase) { @@ -4143,15 +4145,11 @@ public class BatteryStatsImpl extends BatteryStats { } private void requestWakelockCpuUpdate() { - if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) { - Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS); - mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS); - } + mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS); } private void requestImmediateCpuUpdate() { - mHandler.removeMessages(MSG_UPDATE_WAKELOCKS); - mHandler.sendEmptyMessage(MSG_UPDATE_WAKELOCKS); + mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */); } public void setRecordAllHistoryLocked(boolean enabled) { @@ -4554,7 +4552,7 @@ public class BatteryStatsImpl extends BatteryStats { } public boolean startAddingCpuLocked() { - mHandler.removeMessages(MSG_UPDATE_WAKELOCKS); + mExternalSync.cancelCpuSyncDueToWakelockChange(); return mOnBatteryInternal; } @@ -4807,6 +4805,8 @@ public class BatteryStatsImpl extends BatteryStats { + Display.stateToString(state)); addHistoryRecordLocked(elapsedRealtime, uptime); } + mExternalSync.scheduleCpuSyncDueToScreenStateChange( + mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning()); if (isScreenOn(state)) { updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state, mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000); @@ -9196,8 +9196,14 @@ public class BatteryStatsImpl extends BatteryStats { } public void addCpuTimeLocked(int utime, int stime) { - mUserTime += utime; - mSystemTime += stime; + addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning()); + } + + public void addCpuTimeLocked(int utime, int stime, boolean isRunning) { + if (isRunning) { + mUserTime += utime; + mSystemTime += stime; + } } public void addForegroundTimeLocked(long ttime) { @@ -11761,13 +11767,24 @@ public class BatteryStatsImpl extends BatteryStats { } } + public boolean isOnBatteryLocked() { + return mOnBatteryTimeBase.isRunning(); + } + + public boolean isOnBatteryScreenOffLocked() { + return mOnBatteryScreenOffTimeBase.isRunning(); + } + /** * Read and distribute CPU usage across apps. If their are partial wakelocks being held * 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. + * It's possible this will be invoked after the internal battery/screen states are updated, so + * passing the appropriate battery/screen states to try attribute the cpu times to correct + * buckets. */ @GuardedBy("this") - public void updateCpuTimeLocked() { + public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff) { if (mPowerProfile == null) { return; } @@ -11784,7 +11801,7 @@ public class BatteryStatsImpl extends BatteryStats { // usually holding the wakelock on behalf of an app. // And Only distribute cpu power to wakelocks if the screen is off and we're on battery. ArrayList<StopwatchTimer> partialTimersToConsider = null; - if (mOnBatteryScreenOffTimeBase.isRunning()) { + if (onBatteryScreenOff) { partialTimersToConsider = new ArrayList<>(); for (int i = mPartialTimers.size() - 1; i >= 0; --i) { final StopwatchTimer timer = mPartialTimers.get(i); @@ -11802,7 +11819,7 @@ public class BatteryStatsImpl extends BatteryStats { // When the battery is not on, we don't attribute the cpu times to any timers but we still // need to take the snapshots. - if (!mOnBatteryInternal) { + if (!onBattery) { mKernelUidCpuTimeReader.readDelta(null); mKernelUidCpuFreqTimeReader.readDelta(null); if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) { @@ -11818,16 +11835,16 @@ public class BatteryStatsImpl extends BatteryStats { mUserInfoProvider.refreshUserIds(); final SparseLongArray updatedUids = mKernelUidCpuFreqTimeReader.perClusterTimesAvailable() ? null : new SparseLongArray(); - readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids); + readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery); // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu // freqs, so no need to approximate these values. if (updatedUids != null) { - updateClusterSpeedTimes(updatedUids); + updateClusterSpeedTimes(updatedUids, onBattery); } - readKernelUidCpuFreqTimesLocked(partialTimersToConsider); + readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff); if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) { - readKernelUidCpuActiveTimesLocked(); - readKernelUidCpuClusterTimesLocked(); + readKernelUidCpuActiveTimesLocked(onBattery); + readKernelUidCpuClusterTimesLocked(onBattery); } } @@ -11867,7 +11884,7 @@ public class BatteryStatsImpl extends BatteryStats { * @param updatedUids The uids for which times spent at different frequencies are calculated. */ @VisibleForTesting - public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids) { + public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery) { long totalCpuClustersTimeMs = 0; // Read the time spent for each cluster at various cpu frequencies. final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][]; @@ -11909,7 +11926,7 @@ public class BatteryStatsImpl extends BatteryStats { } cpuSpeeds[speed].addCountLocked(appCpuTimeUs * clusterSpeedTimesMs[cluster][speed] - / totalCpuClustersTimeMs); + / totalCpuClustersTimeMs, onBattery); } } } @@ -11926,7 +11943,7 @@ public class BatteryStatsImpl extends BatteryStats { */ @VisibleForTesting public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers, - @Nullable SparseLongArray updatedUids) { + @Nullable SparseLongArray updatedUids, boolean onBattery) { mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0; final int numWakelocks = partialTimers == null ? 0 : partialTimers.size(); final long startTimeMs = mClocks.uptimeMillis(); @@ -11977,8 +11994,8 @@ public class BatteryStatsImpl extends BatteryStats { Slog.d(TAG, sb.toString()); } - u.mUserCpuTime.addCountLocked(userTimeUs); - u.mSystemCpuTime.addCountLocked(systemTimeUs); + u.mUserCpuTime.addCountLocked(userTimeUs, onBattery); + u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery); if (updatedUids != null) { updatedUids.put(u.getUid(), userTimeUs + systemTimeUs); } @@ -12010,15 +12027,15 @@ public class BatteryStatsImpl extends BatteryStats { Slog.d(TAG, sb.toString()); } - timer.mUid.mUserCpuTime.addCountLocked(userTimeUs); - timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs); + timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery); + timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery); if (updatedUids != null) { final int uid = timer.mUid.getUid(); updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs); } final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*"); - proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000); + proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery); mTempTotalCpuUserTimeUs -= userTimeUs; mTempTotalCpuSystemTimeUs -= systemTimeUs; @@ -12033,7 +12050,8 @@ public class BatteryStatsImpl extends BatteryStats { * @param partialTimers The wakelock holders among which the cpu freq times will be distributed. */ @VisibleForTesting - public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers) { + public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers, + boolean onBattery, boolean onBatteryScreenOff) { final boolean perClusterTimesAvailable = mKernelUidCpuFreqTimeReader.perClusterTimesAvailable(); final int numWakelocks = partialTimers == null ? 0 : partialTimers.size(); @@ -12056,13 +12074,13 @@ public class BatteryStatsImpl extends BatteryStats { if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) { u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase); } - u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs); + u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery); if (u.mScreenOffCpuFreqTimeMs == null || u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) { u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray( mOnBatteryScreenOffTimeBase); } - u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs); + u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff); if (perClusterTimesAvailable) { if (u.mCpuClusterSpeedTimesUs == null || @@ -12098,7 +12116,7 @@ public class BatteryStatsImpl extends BatteryStats { } else { appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000; } - cpuTimesUs[speed].addCountLocked(appAllocationUs); + cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery); freqIndex++; } } @@ -12132,7 +12150,7 @@ public class BatteryStatsImpl extends BatteryStats { } final long allocationUs = mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i); - cpuTimeUs[speed].addCountLocked(allocationUs); + cpuTimeUs[speed].addCountLocked(allocationUs, onBattery); mWakeLockAllocationsUs[cluster][speed] -= allocationUs; } } @@ -12145,7 +12163,7 @@ public class BatteryStatsImpl extends BatteryStats { * counters. */ @VisibleForTesting - public void readKernelUidCpuActiveTimesLocked() { + public void readKernelUidCpuActiveTimesLocked(boolean onBattery) { final long startTimeMs = mClocks.uptimeMillis(); mKernelUidCpuActiveTimeReader.readDelta((uid, cpuActiveTimesUs) -> { uid = mapUid(uid); @@ -12160,7 +12178,7 @@ public class BatteryStatsImpl extends BatteryStats { return; } final Uid u = getUidStatsLocked(uid); - u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesUs); + u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesUs, onBattery); }); final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs; @@ -12174,7 +12192,7 @@ public class BatteryStatsImpl extends BatteryStats { * counters. */ @VisibleForTesting - public void readKernelUidCpuClusterTimesLocked() { + public void readKernelUidCpuClusterTimesLocked(boolean onBattery) { final long startTimeMs = mClocks.uptimeMillis(); mKernelUidCpuClusterTimeReader.readDelta((uid, cpuClusterTimesUs) -> { uid = mapUid(uid); @@ -12189,7 +12207,7 @@ public class BatteryStatsImpl extends BatteryStats { return; } final Uid u = getUidStatsLocked(uid); - u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesUs); + u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesUs, onBattery); }); final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs; @@ -12399,9 +12417,7 @@ public class BatteryStatsImpl extends BatteryStats { reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null, status, plugType, level, temp); - final boolean onBattery = - plugType == BATTERY_PLUGGED_NONE && - status != BatteryManager.BATTERY_STATUS_UNKNOWN; + final boolean onBattery = isOnBattery(plugType, status); final long uptime = mClocks.uptimeMillis(); final long elapsedRealtime = mClocks.elapsedRealtime(); if (!mHaveBatteryLevel) { @@ -12591,6 +12607,10 @@ public class BatteryStatsImpl extends BatteryStats { mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh); } + public static boolean isOnBattery(int plugType, int status) { + return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN; + } + // Inform StatsLog of setBatteryState changes. // If this is the first reporting, pass in recentPast == null. private void reportChangesToStatsLog(HistoryItem recentPast, diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java index 65615c0ffb02..444049e7e415 100644 --- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java +++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java @@ -78,10 +78,11 @@ public class KernelUidCpuTimeReader { final long userTimeUs = Long.parseLong(splitter.next(), 10); final long systemTimeUs = Long.parseLong(splitter.next(), 10); + boolean notifyCallback = false; + long userTimeDeltaUs = userTimeUs; + long systemTimeDeltaUs = systemTimeUs; // Only report if there is a callback and if this is not the first read. if (callback != null && mLastTimeReadUs != 0) { - long userTimeDeltaUs = userTimeUs; - long systemTimeDeltaUs = systemTimeUs; int index = mLastUserTimeUs.indexOfKey(uid); if (index >= 0) { userTimeDeltaUs -= mLastUserTimeUs.valueAt(index); @@ -114,12 +115,13 @@ public class KernelUidCpuTimeReader { } } - if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0) { - callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs); - } + notifyCallback = (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0); } mLastUserTimeUs.put(uid, userTimeUs); mLastSystemTimeUs.put(uid, systemTimeUs); + if (notifyCallback) { + callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs); + } } } catch (IOException e) { Slog.e(TAG, "Failed to read uid_cputime: " + e.getMessage()); diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index e69a36064693..fac6b230bff2 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -53,8 +53,8 @@ public final class Zygote { public static final int DISABLE_VERIFIER = 1 << 9; /** Only use oat files located in /system. Otherwise use dex/jar/apk . */ public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10; - /** Do not enfore hidden API access restrictions. */ - public static final int DISABLE_HIDDEN_API_CHECKS = 1 << 11; + /** Do enfore hidden API access restrictions. */ + public static final int ENABLE_HIDDEN_API_CHECKS = 1 << 11; /** Force generation of native debugging information for backtraces. */ public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 12; @@ -160,9 +160,6 @@ public final class Zygote { */ public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { - // SystemServer is always allowed to use hidden APIs. - runtimeFlags |= DISABLE_HIDDEN_API_CHECKS; - VM_HOOKS.preFork(); // Resets nice priority for zygote process. resetNicePriority(); diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 74802c8bdf79..9c8997657474 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -98,10 +98,6 @@ public class ZygoteInit { private static final String SOCKET_NAME_ARG = "--socket-name="; - /* Dexopt flag to disable hidden API access checks when dexopting SystemServer. - * Must be kept in sync with com.android.server.pm.Installer. */ - private static final int DEXOPT_DISABLE_HIDDEN_API_CHECKS = 1 << 10; - /** * Used to pre-load resources. */ @@ -569,10 +565,7 @@ public class ZygoteInit { if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) { final String packageName = "*"; final String outputPath = null; - // Dexopt with a flag which lifts restrictions on hidden API usage. - // Offending methods would otherwise be re-verified at runtime and - // we want to avoid the performance overhead of that. - final int dexFlags = DEXOPT_DISABLE_HIDDEN_API_CHECKS; + final int dexFlags = 0; final String compilerFilter = systemServerFilter; final String uuid = StorageManager.UUID_PRIVATE_INTERNAL; final String seInfo = null; diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 0ef5445afffc..8ca506254f74 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -846,6 +846,14 @@ static void nativeSetOverrideScalingMode(JNIEnv* env, jclass clazz, jlong transa transaction->setOverrideScalingMode(ctrl, scalingMode); } +static void nativeDestroyInTransaction(JNIEnv* env, jclass clazz, + jlong transactionObj, + jlong nativeObject) { + auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); + auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject); + transaction->destroySurface(ctrl); +} + static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) { auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); return javaObjectForIBinder(env, ctrl->getHandle()); @@ -997,6 +1005,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSeverChildren } , {"nativeSetOverrideScalingMode", "(JJI)V", (void*)nativeSetOverrideScalingMode }, + {"nativeDestroy", "(JJ)V", + (void*)nativeDestroyInTransaction }, {"nativeGetHandle", "(J)Landroid/os/IBinder;", (void*)nativeGetHandle }, {"nativeScreenshotToBuffer", diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto index f2b7ab297e20..02fc4da4d220 100644 --- a/core/proto/android/providers/settings.proto +++ b/core/proto/android/providers/settings.proto @@ -399,6 +399,7 @@ message GlobalSettingsProto { optional SettingProto euicc_factory_reset_timeout_millis = 333 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto storage_settings_clobber_threshold = 334 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto chained_battery_attribution_enabled = 353 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto hidden_api_blacklist_exemptions = 355 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Subscription to be used for voice call on a multi sim device. The // supported values are 0 = SUB1, 1 = SUB2 and etc. optional SettingProto multi_sim_voice_call_subscription = 276 [ (android.privacy).dest = DEST_AUTOMATIC ]; @@ -426,10 +427,11 @@ message GlobalSettingsProto { optional SettingProto show_first_crash_dialog = 349 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto show_restart_in_crash_dialog = 351 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto show_mute_in_crash_dialog = 352 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingsProto show_zen_upgrade_notification = 354 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Please insert fields in the same order as in // frameworks/base/core/java/android/provider/Settings.java. - // Next tag = 354; + // Next tag = 356; } message SecureSettingsProto { diff --git a/core/res/res/drawable/ic_settings_24dp.xml b/core/res/res/drawable/ic_settings_24dp.xml index fc75f04ff46b..c70b122358b8 100644 --- a/core/res/res/drawable/ic_settings_24dp.xml +++ b/core/res/res/drawable/ic_settings_24dp.xml @@ -16,9 +16,9 @@ Copyright (C) 2015 The Android Open Source Project <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" - android:viewportWidth="48.0" - android:viewportHeight="48.0"> + android:viewportWidth="24.0" + android:viewportHeight="24.0"> <path - android:fillColor="#FF000000" - android:pathData="M38.86 25.95c.08,-.64.14,-1.29.14,-1.95s-.06,-1.31,-.14,-1.95l4.23,-3.31c.38,-.3.49,-.84.24,-1.28l-4,-6.93c-.25,-.43,-.77,-.61,-1.22,-.43l-4.98 2.01c-1.03,-.79,-2.16,-1.46,-3.38,-1.97L29 4.84c-.09,-.47,-.5,-.84,-1,-.84h-8c-.5 0,-.91.37,-.99.84l-.75 5.3c-1.22.51,-2.35 1.17,-3.38 1.97L9.9 10.1c-.45,-.17,-.97 0,-1.22.43l-4 6.93c-.25.43,-.14.97.24 1.28l4.22 3.31C9.06 22.69 9 23.34 9 24s.06 1.31.14 1.95l-4.22 3.31c-.38.3,-.49.84,-.24 1.28l4 6.93c.25.43.77.61 1.22.43l4.98,-2.01c1.03.79 2.16 1.46 3.38 1.97l.75 5.3c.08.47.49.84.99.84h8c.5 0 .91,-.37.99,-.84l.75,-5.3c1.22,-.51 2.35,-1.17 3.38,-1.97l4.98 2.01c.45.17.97 0 1.22,-.43l4,-6.93c.25,-.43.14,-.97,-.24,-1.28l-4.22,-3.31zM24 31c-3.87 0,-7,-3.13,-7,-7s3.13,-7 7,-7 7 3.13 7 7,-3.13 7,-7 7z"/> + android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z" + android:fillColor="#FF000000" /> </vector> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index cf7925baa578..0218750d0f87 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2913,8 +2913,8 @@ <item name="config_pictureInPictureAspectRatioLimitForMinSize" format="float" type="dimen">1.777778</item> <!-- The default gravity for the picture-in-picture window. - Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT --> - <integer name="config_defaultPictureInPictureGravity">0x55</integer> + Currently, this maps to Gravity.TOP | Gravity.RIGHT --> + <integer name="config_defaultPictureInPictureGravity">0x35</integer> <!-- The minimum aspect ratio (width/height) that is supported for picture-in-picture. Any ratio smaller than this is considered too tall and thin to be usable. Currently, this diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index ec81df7b89e2..0efb6f91fce0 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4854,4 +4854,11 @@ <!-- Notification action for editing a screenshot (drawing on it, cropping it, etc) --> <string name="screenshot_edit">Edit</string> + + <!-- Title for the notification channel notifying user of settings system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] --> + <string name="notification_channel_system_changes">System changes</string> + <!-- Title of notification indicating do not disturb settings have changed when upgrading to P --> + <string name="zen_upgrade_notification_title">Do Not Disturb has changed</string> + <!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings --> + <string name="zen_upgrade_notification_content">Tap to check your behavior settings for interruptions</string> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index af253986577d..5a9dc7fa92be 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1716,6 +1716,7 @@ <java-symbol type="string" name="bugreport_status" /> <java-symbol type="string" name="bugreport_title" /> <java-symbol type="string" name="faceunlock_multiple_failures" /> + <java-symbol type="string" name="global_actions" /> <java-symbol type="string" name="global_action_power_off" /> <java-symbol type="string" name="global_action_restart" /> <java-symbol type="string" name="global_actions_airplane_mode_off_status" /> @@ -3102,6 +3103,7 @@ <java-symbol type="string" name="notification_channel_retail_mode" /> <java-symbol type="string" name="notification_channel_usb" /> <java-symbol type="string" name="notification_channel_heavy_weight_app" /> + <java-symbol type="string" name="notification_channel_system_changes" /> <java-symbol type="string" name="config_defaultAutofillService" /> <java-symbol type="string" name="config_defaultTextClassifierService" /> @@ -3257,4 +3259,7 @@ <!-- For Wear devices --> <java-symbol type="array" name="config_wearActivityModeRadios" /> + + <java-symbol type="string" name="zen_upgrade_notification_title" /> + <java-symbol type="string" name="zen_upgrade_notification_content" /> </resources> diff --git a/core/res/res/xml/default_zen_mode_config.xml b/core/res/res/xml/default_zen_mode_config.xml index a446088fb93d..7849a2ace638 100644 --- a/core/res/res/xml/default_zen_mode_config.xml +++ b/core/res/res/xml/default_zen_mode_config.xml @@ -18,7 +18,7 @@ --> <!-- Default configuration for zen mode. See android.service.notification.ZenModeConfig. --> -<zen version="2"> +<zen version="3"> <allow alarms="true" media_system_other="true" calls="false" messages="false" reminders="false" events="false" /> </zen> diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index a0b6297db235..dc8ed9efaa76 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -354,6 +354,7 @@ public class SettingsBackupTest { Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG, Settings.Global.SHOW_TEMPERATURE_WARNING, + Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL, Settings.Global.SMART_SELECTION_UPDATE_METADATA_URL, Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS, @@ -451,7 +452,8 @@ public class SettingsBackupTest { Settings.Global.ZEN_MODE_RINGER_LEVEL, Settings.Global.ZRAM_ENABLED, Settings.Global.OVERRIDE_SETTINGS_PROVIDER_RESTORE_ANY_VERSION, - Settings.Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED); + Settings.Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED, + Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS); private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS = newHashSet( diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java index 32053e30e886..cb049b780fa8 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java @@ -114,7 +114,7 @@ public class BatteryStatsCpuTimesTest { when(mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile)).thenReturn(freqs); // RUN - mBatteryStatsImpl.updateCpuTimeLocked(); + mBatteryStatsImpl.updateCpuTimeLocked(false, false); // VERIFY assertArrayEquals("Unexpected cpu freqs", freqs, mBatteryStatsImpl.getCpuFreqs()); @@ -134,7 +134,7 @@ public class BatteryStatsCpuTimesTest { mBatteryStatsImpl.setOnBatteryInternal(true); // RUN - mBatteryStatsImpl.updateCpuTimeLocked(); + mBatteryStatsImpl.updateCpuTimeLocked(true, false); // VERIFY verify(mUserInfoProvider).refreshUserIds(); @@ -213,7 +213,7 @@ public class BatteryStatsCpuTimesTest { } // RUN - mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids); + mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids, true); // VERIFY int totalClustersTimeMs = 0; @@ -261,7 +261,7 @@ public class BatteryStatsCpuTimesTest { // RUN final SparseLongArray updatedUids = new SparseLongArray(); - mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, updatedUids); + mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, updatedUids, true); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -294,7 +294,7 @@ public class BatteryStatsCpuTimesTest { }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null); + mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -333,7 +333,7 @@ public class BatteryStatsCpuTimesTest { }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null); + mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -368,7 +368,7 @@ public class BatteryStatsCpuTimesTest { }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null); + mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -423,7 +423,7 @@ public class BatteryStatsCpuTimesTest { }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null); + mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -470,7 +470,7 @@ public class BatteryStatsCpuTimesTest { // RUN final SparseLongArray updatedUids = new SparseLongArray(); - mBatteryStatsImpl.readKernelUidCpuTimesLocked(partialTimers, updatedUids); + mBatteryStatsImpl.readKernelUidCpuTimesLocked(partialTimers, updatedUids, true); // VERIFY long totalUserTimeUs = 0; @@ -549,7 +549,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -582,7 +582,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -633,7 +633,7 @@ public class BatteryStatsCpuTimesTest { when(mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()).thenReturn(true); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -676,7 +676,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -743,7 +743,7 @@ public class BatteryStatsCpuTimesTest { when(mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()).thenReturn(true); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(partialTimers); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(partialTimers, true, false); // VERIFY final long[][] expectedWakeLockUidTimesUs = new long[clusterFreqs.length][]; @@ -832,7 +832,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -865,7 +865,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -909,7 +909,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -949,7 +949,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -1006,7 +1006,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuFreqTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null); + mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -1047,7 +1047,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuActiveTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(); + mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -1073,7 +1073,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuActiveTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(); + mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -1112,7 +1112,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuClusterTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(); + mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true); // VERIFY for (int i = 0; i < testUids.length; ++i) { @@ -1142,7 +1142,7 @@ public class BatteryStatsCpuTimesTest { any(KernelUidCpuClusterTimeReader.Callback.class)); // RUN - mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(); + mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true); // VERIFY for (int i = 0; i < testUids.length; ++i) { diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java index 82ac9da575d7..01ddc15efb47 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java @@ -161,9 +161,7 @@ public class BatteryStatsNoteTest extends TestCase { actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE, elapsedTimeUs, STATS_SINCE_CHARGED); - expectedRunTimeMs = stateRuntimeMap.get( - ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) - + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); + expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs); actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING, @@ -173,7 +171,8 @@ public class BatteryStatsNoteTest extends TestCase { actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND, elapsedTimeUs, STATS_SINCE_CHARGED); - expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND); + expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) + + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs); actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_BACKGROUND, diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java index 7b239f05c0d3..cb05253c6f57 100644 --- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java +++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java @@ -171,6 +171,20 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { return null; } + @Override + public Future<?> scheduleCpuSyncDueToScreenStateChange( + boolean onBattery, boolean onBatteryScreenOff) { + return null; + } + + @Override + public Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis) { + return null; + } + + @Override + public void cancelCpuSyncDueToWakelockChange() { + } } } diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 0be54ec2b2d9..9ff964b3f0d4 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -16,6 +16,7 @@ package android.media; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -65,6 +66,8 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; + /** * AudioManager provides access to volume and ringer mode control. @@ -4864,6 +4867,114 @@ public class AudioManager { } } + + /** + * @hide + * Abstract class to receive event notification about audioserver process state. + */ + @SystemApi + public abstract static class AudioServerStateCallback { + public void onAudioServerDown() { } + public void onAudioServerUp() { } + } + + private Executor mAudioServerStateExec; + private AudioServerStateCallback mAudioServerStateCb; + private final Object mAudioServerStateCbLock = new Object(); + + private final IAudioServerStateDispatcher mAudioServerStateDispatcher = + new IAudioServerStateDispatcher.Stub() { + @Override + public void dispatchAudioServerStateChange(boolean state) { + Executor exec; + AudioServerStateCallback cb; + + synchronized (mAudioServerStateCbLock) { + exec = mAudioServerStateExec; + cb = mAudioServerStateCb; + } + + if ((exec == null) || (cb == null)) { + return; + } + if (state) { + exec.execute(() -> cb.onAudioServerUp()); + } else { + exec.execute(() -> cb.onAudioServerDown()); + } + } + }; + + /** + * @hide + * Registers a callback for notification of audio server state changes. + * @param executor {@link Executor} to handle the callbacks + * @param stateCallback the callback to receive the audio server state changes + * To remove the callabck, pass a null reference for both executor and stateCallback. + */ + @SystemApi + public void setAudioServerStateCallback(@NonNull Executor executor, + @NonNull AudioServerStateCallback stateCallback) { + if (stateCallback == null) { + throw new IllegalArgumentException("Illegal null AudioServerStateCallback"); + } + if (executor == null) { + throw new IllegalArgumentException( + "Illegal null Executor for the AudioServerStateCallback"); + } + + synchronized (mAudioServerStateCbLock) { + if (mAudioServerStateCb != null) { + throw new IllegalStateException( + "setAudioServerStateCallback called with already registered callabck"); + } + final IAudioService service = getService(); + try { + service.registerAudioServerStateDispatcher(mAudioServerStateDispatcher); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + mAudioServerStateExec = executor; + mAudioServerStateCb = stateCallback; + } + } + + /** + * @hide + * Unregisters the callback for notification of audio server state changes. + */ + @SystemApi + public void clearAudioServerStateCallback() { + synchronized (mAudioServerStateCbLock) { + if (mAudioServerStateCb != null) { + final IAudioService service = getService(); + try { + service.unregisterAudioServerStateDispatcher( + mAudioServerStateDispatcher); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + mAudioServerStateExec = null; + mAudioServerStateCb = null; + } + } + + /** + * @hide + * Checks if native audioservice is running or not. + * @return true if native audioservice runs, false otherwise. + */ + @SystemApi + public boolean isAudioServerRunning() { + final IAudioService service = getService(); + try { + return service.isAudioServerRunning(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + //--------------------------------------------------------- // Inner classes //-------------------- diff --git a/core/java/android/security/keymaster/KeymasterArguments.aidl b/media/java/android/media/IAudioServerStateDispatcher.aidl index 44d9f0954781..2bc90eaf1780 100644 --- a/core/java/android/security/keymaster/KeymasterArguments.aidl +++ b/media/java/android/media/IAudioServerStateDispatcher.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,15 @@ * limitations under the License. */ -package android.security.keymaster; +package android.media; -/* @hide */ -parcelable KeymasterArguments cpp_header "keystore/KeymasterArguments.h"; +/** + * AIDL for the AudioService to signal audio server state changes + * + * {@hide} + */ +oneway interface IAudioServerStateDispatcher { + + void dispatchAudioServerStateChange(boolean state); + +} diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 4c37014b7397..05ba4c35c21d 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -24,10 +24,12 @@ import android.media.AudioRecordingConfiguration; import android.media.AudioRoutesInfo; import android.media.IAudioFocusDispatcher; import android.media.IAudioRoutesObserver; +import android.media.IAudioServerStateDispatcher; import android.media.IPlaybackConfigDispatcher; import android.media.IRecordingConfigDispatcher; import android.media.IRingtonePlayer; import android.media.IVolumeController; +import android.media.IVolumeController; import android.media.PlayerBase; import android.media.VolumePolicy; import android.media.audiopolicy.AudioPolicyConfig; @@ -208,6 +210,12 @@ interface IAudioService { oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult, in IAudioPolicyCallback pcb); + void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd); + + oneway void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd); + + boolean isAudioServerRunning(); + // WARNING: read warning at top of file, new methods that need to be used by native // code via IAudioManager.h need to be added to the top section. } diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index b8184a0789b6..b8d01c44348b 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -119,7 +119,8 @@ public final class MediaSession { private final ISession mBinder; private final CallbackStub mCbStub; - private CallbackMessageHandler mCallbackHandler; + // Do not change the name of mCallback. Support lib accesses this by using reflection. + private CallbackMessageHandler mCallback; private VolumeProvider mVolumeProvider; private PlaybackState mPlaybackState; @@ -194,13 +195,13 @@ public final class MediaSession { */ public void setCallback(@Nullable Callback callback, @Nullable Handler handler) { synchronized (mLock) { - if (mCallbackHandler != null) { + if (mCallback != null) { // We're updating the callback, clear the session from the old one. - mCallbackHandler.mCallback.mSession = null; - mCallbackHandler.removeCallbacksAndMessages(null); + mCallback.mCallback.mSession = null; + mCallback.removeCallbacksAndMessages(null); } if (callback == null) { - mCallbackHandler = null; + mCallback = null; return; } if (handler == null) { @@ -209,7 +210,7 @@ public final class MediaSession { callback.mSession = this; CallbackMessageHandler msgHandler = new CallbackMessageHandler(handler.getLooper(), callback); - mCallbackHandler = msgHandler; + mCallback = msgHandler; } } @@ -634,8 +635,8 @@ public final class MediaSession { private void postToCallback(int what, Object obj, Bundle extras) { synchronized (mLock) { - if (mCallbackHandler != null) { - mCallbackHandler.post(what, obj, extras); + if (mCallback != null) { + mCallback.post(what, obj, extras); } } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 1551b8e2eea9..769b7e9a13c5 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1055,6 +1055,9 @@ class SettingsProtoDumpUtil { Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED, GlobalSettingsProto.CHAINED_BATTERY_ATTRIBUTION_ENABLED); dumpSetting(s, p, + Global.HIDDEN_API_BLACKLIST_EXEMPTIONS, + GlobalSettingsProto.HIDDEN_API_BLACKLIST_EXEMPTIONS); + dumpSetting(s, p, Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION, GlobalSettingsProto.MULTI_SIM_VOICE_CALL_SUBSCRIPTION); dumpSetting(s, p, @@ -1123,6 +1126,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG, GlobalSettingsProto.SHOW_MUTE_IN_CRASH_DIALOG); + dumpSetting(s, p, + Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, + GlobalSettingsProto.SHOW_ZEN_UPGRADE_NOTIFICATION); // Please insert new settings using the same order as in Settings.Global. } diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml index faa2c17b63bf..31635a507d6f 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml @@ -33,6 +33,23 @@ android:layout_height="wrap_content" android:layout_marginBottom="@dimen/widget_vertical_padding" android:orientation="vertical"> + <TextView + android:id="@+id/logout" + android:layout_height="@dimen/logout_button_layout_height" + android:layout_width="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_centerHorizontal="true" + android:layout_marginBottom="@dimen/logout_button_margin_bottom" + android:gravity="center" + android:paddingLeft="@dimen/logout_button_padding_horizontal" + android:paddingRight="@dimen/logout_button_padding_horizontal" + android:background="@drawable/logout_button_background" + android:fontFamily="roboto-medium" + android:textAllCaps="true" + android:textColor="?android:attr/textColorPrimary" + android:textSize="13sp" + android:text="@*android:string/global_action_logout" /> + <RelativeLayout android:id="@+id/keyguard_clock_container" android:layout_width="match_parent" diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step.png Binary files differnew file mode 100644 index 000000000000..2d62a80a63ba --- /dev/null +++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step.png diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step_dark.png Binary files differnew file mode 100644 index 000000000000..a52e5b10fcf3 --- /dev/null +++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step_dark.png diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step.png Binary files differnew file mode 100644 index 000000000000..d13c730d4f7a --- /dev/null +++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step.png diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step_dark.png Binary files differnew file mode 100644 index 000000000000..31c602e8d2d6 --- /dev/null +++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step_dark.png diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step.png Binary files differnew file mode 100644 index 000000000000..ddbcb07dacfb --- /dev/null +++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step.png diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step_dark.png Binary files differnew file mode 100644 index 000000000000..ce91fcbb24b2 --- /dev/null +++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step_dark.png diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step.png Binary files differnew file mode 100644 index 000000000000..c606a58c247e --- /dev/null +++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step.png diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step_dark.png Binary files differnew file mode 100644 index 000000000000..c2a5fef89799 --- /dev/null +++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step_dark.png diff --git a/packages/SystemUI/res/drawable/ic_lock_lockdown.xml b/packages/SystemUI/res/drawable/ic_lock_lockdown.xml new file mode 100644 index 000000000000..b517fc89e094 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_lock_lockdown.xml @@ -0,0 +1,25 @@ +<!-- +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24.0dp" + android:height="24.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + + <path + android:fillColor="#757575" + android:pathData="M18.0,8.0l-1.0,0.0L17.0,6.0c0.0,-2.8 -2.2,-5.0 -5.0,-5.0C9.2,1.0 7.0,3.2 7.0,6.0l0.0,2.0L6.0,8.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,10.0c0.0,1.1 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,10.0C20.0,8.9 19.1,8.0 18.0,8.0zM12.0,17.0c-1.1,0.0 -2.0,-0.9 -2.0,-2.0s0.9,-2.0 2.0,-2.0c1.1,0.0 2.0,0.9 2.0,2.0S13.1,17.0 12.0,17.0zM15.1,8.0L8.9,8.0L8.9,6.0c0.0,-1.7 1.4,-3.1 3.1,-3.1c1.7,0.0 3.1,1.4 3.1,3.1L15.1,8.0z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/logout_button_background.xml b/packages/SystemUI/res/drawable/logout_button_background.xml new file mode 100644 index 000000000000..eafd663f19d9 --- /dev/null +++ b/packages/SystemUI/res/drawable/logout_button_background.xml @@ -0,0 +1,23 @@ +<?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 + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="@color/logout_button_bg_color"/> + <corners android:radius="@dimen/logout_button_corner_radius"/> +</shape> diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml index 8078c4121424..24709478e076 100644 --- a/packages/SystemUI/res/layout/menu_ime.xml +++ b/packages/SystemUI/res/layout/menu_ime.xml @@ -41,6 +41,15 @@ android:scaleType="centerInside" /> <com.android.systemui.statusbar.policy.KeyButtonView + android:id="@+id/rotate_suggestion" + android:layout_width="@dimen/navigation_extra_key_width" + android:layout_height="match_parent" + android:layout_marginEnd="2dp" + android:visibility="invisible" + android:scaleType="centerInside" + android:contentDescription="@string/accessibility_rotate_button" + /> + <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/accessibility_button" android:layout_width="@dimen/navigation_extra_key_width" android:layout_height="match_parent" diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 4fcfdf7558f9..be8e990fb075 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -166,4 +166,6 @@ <color name="fingerprint_dialog_dim_color">#80000000</color> <!-- 50% black --> <color name="fingerprint_error_message_color">#ff5722</color> + <!-- Logout button --> + <color name="logout_button_bg_color">#ccffffff</color> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 3f6c85fc67ad..a62f38b946ee 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -884,7 +884,7 @@ <dimen name="nav_quick_scrub_track_thickness">2dp</dimen> <!-- Home button padding for sizing --> - <dimen name="home_padding">15dp</dimen> + <dimen name="home_padding">16dp</dimen> <!-- Smart reply button --> <dimen name="smart_reply_button_corner_radius">24dip</dimen> @@ -925,4 +925,10 @@ <integer name="wired_charging_aod_text_animation_duration_up">300</integer> <!-- Wired charging on AOD, text animation distance --> <integer name="wired_charging_aod_text_animation_distance">-30</integer> + + <!-- Logout button --> + <dimen name="logout_button_layout_height">32dp</dimen> + <dimen name="logout_button_padding_horizontal">16dp</dimen> + <dimen name="logout_button_margin_bottom">12dp</dimen> + <dimen name="logout_button_corner_radius">2dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index dc082a99d53e..8c59e75315a1 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1751,15 +1751,13 @@ <string-array name="nav_bar_buttons"> <item>Clipboard</item> <item>Keycode</item> - <item>Keyboard switcher</item> - <item>Rotation suggestion</item> + <item>Rotate confirm, keyboard switcher</item> <item>None</item> </string-array> <string-array name="nav_bar_button_values" translatable="false"> <item>clipboard</item> <item>key</item> <item>menu_ime</item> - <item>rotate</item> <item>space</item> </string-array> 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 7f382acb0aab..e200a7fee4e6 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 @@ -23,6 +23,14 @@ oneway interface IOverviewProxy { void onBind(in ISystemUiProxy sysUiProxy); /** + * Called once immediately prior to the first onMotionEvent() call, providing a hint to the + * target the initial source of the subsequent motion events. + * + * @param downHitTarget is one of the {@link NavigationBarCompat.HitTarget}s + */ + void onPreMotionEvent(int downHitTarget); + + /** * Proxies motion events from the nav bar in SystemUI to the OverviewProxyService. The sender * guarantees the following order of events: * diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java index 62bd72f393cc..138910cb9820 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java @@ -316,6 +316,17 @@ public class ActivityManagerWrapper { } /** + * Cancels the remote recents animation started from {@link #startRecentsActivity}. + */ + public void cancelRecentsAnimation() { + try { + ActivityManager.getService().cancelRecentsAnimation(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to cancel recents animation", e); + } + } + + /** * Starts a task from Recents. * * @see {@link #startActivityFromRecentsAsync(TaskKey, ActivityOptions, int, int, Consumer, Handler)} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java new file mode 100644 index 000000000000..f622d4a3338c --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java @@ -0,0 +1,31 @@ +/* + * 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.systemui.shared.system; + +import android.annotation.IntDef; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +public class NavigationBarCompat { + @Retention(RetentionPolicy.SOURCE) + @IntDef({HIT_TARGET_NONE, HIT_TARGET_BACK, HIT_TARGET_HOME}) + public @interface HitTarget{} + + public static final int HIT_TARGET_NONE = 0; + public static final int HIT_TARGET_BACK = 1; + public static final int HIT_TARGET_HOME = 2; +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java index e440731dcd47..3b5f34cd84cc 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java @@ -16,13 +16,16 @@ package com.android.keyguard; +import android.app.ActivityManager; import android.app.AlarmManager; +import android.app.IActivityManager; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Color; import android.os.Handler; import android.os.Looper; +import android.os.RemoteException; import android.os.UserHandle; import android.support.v4.graphics.ColorUtils; import android.text.TextUtils; @@ -51,9 +54,11 @@ public class KeyguardStatusView extends GridLayout { private final LockPatternUtils mLockPatternUtils; private final AlarmManager mAlarmManager; + private final IActivityManager mIActivityManager; private final float mSmallClockScale; private final float mWidgetPadding; + private TextView mLogoutView; private TextClock mClockView; private View mClockSeparator; private TextView mOwnerInfo; @@ -80,6 +85,7 @@ public class KeyguardStatusView extends GridLayout { if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing); refresh(); updateOwnerInfo(); + updateLogoutView(); } } @@ -97,6 +103,12 @@ public class KeyguardStatusView extends GridLayout { public void onUserSwitchComplete(int userId) { refresh(); updateOwnerInfo(); + updateLogoutView(); + } + + @Override + public void onLogoutEnabledChanged() { + updateLogoutView(); } }; @@ -111,6 +123,7 @@ public class KeyguardStatusView extends GridLayout { public KeyguardStatusView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + mIActivityManager = ActivityManager.getService(); mLockPatternUtils = new LockPatternUtils(getContext()); mHandler = new Handler(Looper.myLooper()); mSmallClockScale = getResources().getDimension(R.dimen.widget_small_font_size) @@ -145,6 +158,9 @@ public class KeyguardStatusView extends GridLayout { @Override protected void onFinishInflate() { super.onFinishInflate(); + mLogoutView = findViewById(R.id.logout); + mLogoutView.setOnClickListener(this::onLogoutClicked); + mClockContainer = findViewById(R.id.keyguard_clock_container); mClockView = findViewById(R.id.clock_view); mClockView.setShowCurrentUserTime(true); @@ -164,6 +180,7 @@ public class KeyguardStatusView extends GridLayout { setEnableMarquee(shouldMarquee); refresh(); updateOwnerInfo(); + updateLogoutView(); // Disable elegant text height because our fancy colon makes the ymin value huge for no // reason. @@ -213,14 +230,28 @@ public class KeyguardStatusView extends GridLayout { } public int getClockBottom() { - return mKeyguardSlice.getVisibility() == VISIBLE ? mKeyguardSlice.getBottom() - : mClockView.getBottom(); + if (mOwnerInfo != null && mOwnerInfo.getVisibility() == VISIBLE) { + return mOwnerInfo.getBottom(); + } else { + return mClockContainer.getBottom(); + } + } + + public int getLogoutButtonHeight() { + return mLogoutView.getVisibility() == VISIBLE ? mLogoutView.getHeight() : 0; } public float getClockTextSize() { return mClockView.getTextSize(); } + private void updateLogoutView() { + mLogoutView.setVisibility(shouldShowLogout() ? VISIBLE : GONE); + // Logout button will stay in language of user 0 if we don't set that manually. + mLogoutView.setText(mContext.getResources().getString( + com.android.internal.R.string.global_action_logout)); + } + private void updateOwnerInfo() { if (mOwnerInfo == null) return; String ownerInfo = getOwnerInfo(); @@ -309,6 +340,7 @@ public class KeyguardStatusView extends GridLayout { mDarkAmount = darkAmount; boolean dark = darkAmount == 1; + mLogoutView.setAlpha(dark ? 0 : 1); final int N = mClockContainer.getChildCount(); for (int i = 0; i < N; i++) { View child = mClockContainer.getChildAt(i); @@ -340,4 +372,19 @@ public class KeyguardStatusView extends GridLayout { child.setAlpha(mDarkAmount == 1 && mPulsing ? 0.8f : 1); } } + + private boolean shouldShowLogout() { + return KeyguardUpdateMonitor.getInstance(mContext).isLogoutEnabled() + && KeyguardUpdateMonitor.getCurrentUser() != UserHandle.USER_SYSTEM; + } + + private void onLogoutClicked(View view) { + int currentUserId = KeyguardUpdateMonitor.getCurrentUser(); + try { + mIActivityManager.switchUser(UserHandle.USER_SYSTEM); + mIActivityManager.stopUser(currentUserId, true /*force*/, null); + } catch (RemoteException re) { + Log.e(TAG, "Failed to logout user", re); + } + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 9e4b4055a289..f3f8d91f794b 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -141,6 +141,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final int MSG_USER_UNLOCKED = 334; private static final int MSG_ASSISTANT_STACK_CHANGED = 335; private static final int MSG_FINGERPRINT_AUTHENTICATION_CONTINUE = 336; + private static final int MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED = 337; /** Fingerprint state: Not listening to fingerprint. */ private static final int FINGERPRINT_STATE_STOPPED = 0; @@ -225,6 +226,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private LockPatternUtils mLockPatternUtils; private final IDreamManager mDreamManager; private boolean mIsDreaming; + private final DevicePolicyManager mDevicePolicyManager; + private boolean mLogoutEnabled; /** * Short delay before restarting fingerprint authentication after a successful try @@ -330,6 +333,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { case MSG_FINGERPRINT_AUTHENTICATION_CONTINUE: updateFingerprintListeningState(); break; + case MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED: + updateLogoutEnabled(); + break; } } }; @@ -795,6 +801,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } mHandler.sendMessage( mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, 0, serviceState)); + } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals( + action)) { + mHandler.sendEmptyMessage(MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED); } } }; @@ -1159,6 +1168,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); + filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); context.registerReceiver(mBroadcastReceiver, filter); final IntentFilter bootCompleteFilter = new IntentFilter(); @@ -1213,6 +1223,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener); mUserManager = context.getSystemService(UserManager.class); + mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class); + mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled(); } private void updateFingerprintListeningState() { @@ -1936,6 +1948,26 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { return null; // not found } + /** + * @return a cached version of DevicePolicyManager.isLogoutEnabled() + */ + public boolean isLogoutEnabled() { + return mLogoutEnabled; + } + + private void updateLogoutEnabled() { + boolean logoutEnabled = mDevicePolicyManager.isLogoutEnabled(); + if (mLogoutEnabled != logoutEnabled) { + mLogoutEnabled = logoutEnabled; + for (int i = 0; i < mCallbacks.size(); i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onLogoutEnabledChanged(); + } + } + } + } + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("KeyguardUpdateMonitor state:"); pw.println(" SIM States:"); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index 1afcca64de69..67571bb2ab38 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -283,4 +283,11 @@ public class KeyguardUpdateMonitorCallback { * @see KeyguardIndicationController#showTransientIndication(CharSequence) */ public void onTrustAgentErrorMessage(CharSequence message) { } + + + /** + * Called when a value of logout enabled is change. + */ + public void onLogoutEnabledChanged() { } + } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index c28b7eed1614..259bff28d458 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -688,7 +688,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, } private Action getLockdownAction() { - return new SinglePressAction(R.drawable.ic_lock_lock, + return new SinglePressAction(com.android.systemui.R.drawable.ic_lock_lockdown, R.string.global_action_lockdown) { @Override @@ -1369,6 +1369,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, mListView = findViewById(android.R.id.list); mHardwareLayout = HardwareUiLayout.get(mListView); mHardwareLayout.setOutsideTouchListener(view -> dismiss()); + setTitle(R.string.global_actions); } private void updateList() { @@ -1464,20 +1465,6 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, } @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { - for (int i = 0; i < mAdapter.getCount(); ++i) { - CharSequence label = - mAdapter.getItem(i).getLabelForAccessibility(getContext()); - if (label != null) { - event.getText().add(label); - } - } - } - return super.dispatchPopulateAccessibilityEvent(event); - } - - @Override public void onColorsChanged(ColorExtractor extractor, int which) { if (mKeyguardShowing) { if ((WallpaperManager.FLAG_LOCK & which) != 0) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index eb5619b11487..0876507465a1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -308,6 +308,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } } + public void setRippleAllowed(boolean allowed) { + mBackgroundNormal.setPressedAllowed(allowed); + } + private boolean handleTouchEventDimmed(MotionEvent event) { if (mNeedsDimming && !mDimmed) { // We're actually dimmed, but our content isn't dimmable, let's ensure we have a ripple diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index b3f68d357083..2723df73aa52 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -370,14 +370,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mNotificationInflater.inflateNotificationViews(); } - @Override - public void setPressed(boolean pressed) { - if (isOnKeyguard() || mEntry.notification.getNotification().contentIntent == null) { - // We're dropping the ripple if we have a collapse / launch animation - super.setPressed(pressed); - } - } - public void onNotificationUpdated() { for (NotificationContentView l : mLayouts) { l.onNotificationUpdated(mEntry); @@ -407,6 +399,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView showBlockingHelper(mEntry.userSentiment == NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE); + updateRippleAllowed(); } @VisibleForTesting @@ -1805,6 +1798,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf); } } + updateRippleAllowed(); + } + + private void updateRippleAllowed() { + boolean allowed = isOnKeyguard() + || mEntry.notification.getNotification().contentIntent == null; + setRippleAllowed(allowed); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java index ab89a5287cdb..0ff4dde580b7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java @@ -28,6 +28,7 @@ import android.graphics.drawable.RippleDrawable; import android.util.AttributeSet; import android.view.View; +import com.android.internal.util.ArrayUtils; import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; @@ -50,6 +51,7 @@ public class NotificationBackgroundView extends View { private boolean mExpandAnimationRunning; private float mActualWidth; private int mDrawableAlpha = 255; + private boolean mIsPressedAllowed; public NotificationBackgroundView(Context context, AttributeSet attrs) { super(context, attrs); @@ -94,13 +96,7 @@ public class NotificationBackgroundView extends View { @Override protected void drawableStateChanged() { - drawableStateChanged(mBackground); - } - - private void drawableStateChanged(Drawable d) { - if (d != null && d.isStateful()) { - d.setState(getDrawableState()); - } + setState(getDrawableState()); } @Override @@ -177,7 +173,13 @@ public class NotificationBackgroundView extends View { } public void setState(int[] drawableState) { - mBackground.setState(drawableState); + if (mBackground != null && mBackground.isStateful()) { + if (!mIsPressedAllowed) { + drawableState = ArrayUtils.removeInt(drawableState, + com.android.internal.R.attr.state_pressed); + } + mBackground.setState(drawableState); + } } public void setRippleColor(int color) { @@ -258,4 +260,8 @@ public class NotificationBackgroundView extends View { } invalidate(); } + + public void setPressedAllowed(boolean allowed) { + mIsPressedAllowed = allowed; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java index 1239a9ea0240..72938c25b753 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -114,8 +114,6 @@ public class NavigationBarFragment extends Fragment implements Callbacks { /** Allow some time inbetween the long press for back and recents. */ private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200; - private static final int BUTTON_FADE_IN_OUT_DURATION_MS = 100; - protected NavigationBarView mNavigationBarView = null; protected AssistManager mAssistManager; @@ -152,7 +150,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks { private RotationLockController mRotationLockController; private TaskStackListenerImpl mTaskStackListener; - private final Runnable mRemoveRotationProposal = () -> setRotateSuggestionButtonState(false); + private final Runnable mRemoveRotationProposal = () -> safeSetRotationButtonState(false); private Animator mRotateShowAnimator; private Animator mRotateHideAnimator; @@ -361,22 +359,32 @@ public class NavigationBarFragment extends Fragment implements Callbacks { // rotate button if shown. if (!isValid) { - setRotateSuggestionButtonState(false); + safeSetRotationButtonState(false); return; } if (rotation == mWindowManager.getDefaultDisplay().getRotation()) { // Use this as a signal to remove any current suggestions getView().getHandler().removeCallbacks(mRemoveRotationProposal); - setRotateSuggestionButtonState(false); + safeSetRotationButtonState(false); } else { mLastRotationSuggestion = rotation; // Remember rotation for click - setRotateSuggestionButtonState(true); + safeSetRotationButtonState(true); rescheduleRotationTimeout(false); mMetricsLogger.visible(MetricsEvent.ROTATION_SUGGESTION_SHOWN); } } + private void safeSetRotationButtonState(boolean vis) { + if (mNavigationBarView != null) mNavigationBarView.setRotateSuggestionButtonState(vis); + } + + private void safeSetRotationButtonState(boolean vis, boolean force) { + if (mNavigationBarView != null) { + mNavigationBarView.setRotateSuggestionButtonState(vis, force); + } + } + private void rescheduleRotationTimeout(final boolean reasonHover) { // May be called due to a new rotation proposal or a change in hover state if (reasonHover) { @@ -402,84 +410,6 @@ public class NavigationBarFragment extends Fragment implements Callbacks { return 6000; } - public void setRotateSuggestionButtonState(final boolean visible) { - setRotateSuggestionButtonState(visible, false); - } - - public void setRotateSuggestionButtonState(final boolean visible, final boolean skipAnim) { - ButtonDispatcher rotBtn = mNavigationBarView.getRotateSuggestionButton(); - final boolean currentlyVisible = rotBtn.getVisibility() == View.VISIBLE; - - // Rerun a show animation to indicate change but don't rerun a hide animation - if (!visible && !currentlyVisible) return; - - View currentView = rotBtn.getCurrentView(); - if (currentView == null) return; - - KeyButtonDrawable kbd = rotBtn.getImageDrawable(); - if (kbd == null) return; - - AnimatedVectorDrawable animIcon = null; - if (kbd.getDrawable(0) instanceof AnimatedVectorDrawable) { - animIcon = (AnimatedVectorDrawable) kbd.getDrawable(0); - } - - if (visible) { // Appear and change - rotBtn.setVisibility(View.VISIBLE); - mNavigationBarView.notifySubtreeAccessibilityStateChangedIfNeeded(); - - if (skipAnim) { - currentView.setAlpha(1f); - return; - } - - // Start a new animation if running - if (mRotateShowAnimator != null) mRotateShowAnimator.pause(); - if (mRotateHideAnimator != null) mRotateHideAnimator.pause(); - - ObjectAnimator appearFade = ObjectAnimator.ofFloat(currentView, "alpha", - 0f, 1f); - appearFade.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS); - appearFade.setInterpolator(Interpolators.LINEAR); - mRotateShowAnimator = appearFade; - appearFade.start(); - - // Run the rotate icon's animation if it has one - if (animIcon != null) { - animIcon.reset(); - animIcon.start(); - } - - } else { // Hide - - if (skipAnim) { - rotBtn.setVisibility(View.INVISIBLE); - mNavigationBarView.notifySubtreeAccessibilityStateChangedIfNeeded(); - return; - } - - // Don't start any new hide animations if one is running - if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) return; - // Pause any active show animations but don't reset the AVD to avoid jumps - if (mRotateShowAnimator != null) mRotateShowAnimator.pause(); - - ObjectAnimator fadeOut = ObjectAnimator.ofFloat(currentView, "alpha", - 0f); - fadeOut.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS); - fadeOut.setInterpolator(Interpolators.LINEAR); - fadeOut.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - rotBtn.setVisibility(View.INVISIBLE); - mNavigationBarView.notifySubtreeAccessibilityStateChangedIfNeeded(); - } - }); - - mRotateHideAnimator = fadeOut; - fadeOut.start(); - } - } - // Injected from StatusBar at creation. public void setCurrentSysuiVisibility(int systemUiVisibility) { mSystemUiVisibility = systemUiVisibility; @@ -892,7 +822,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks { if (shouldOverrideUserLockPrefs(rotation)) { mRotationLockController.setRotationLockedAtAngle(true, rotation); } - setRotateSuggestionButtonState(false, true); + safeSetRotationButtonState(false, true); } if (mNavigationBarView != null @@ -928,22 +858,22 @@ public class NavigationBarFragment extends Fragment implements Callbacks { @Override public void onTaskStackChanged() { - setRotateSuggestionButtonState(false); + safeSetRotationButtonState(false); } @Override public void onTaskRemoved(int taskId) { - setRotateSuggestionButtonState(false); + safeSetRotationButtonState(false); } @Override public void onTaskMovedToFront(int taskId) { - setRotateSuggestionButtonState(false); + safeSetRotationButtonState(false); } @Override public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { - setRotateSuggestionButtonState(false); + safeSetRotationButtonState(false); } } @@ -960,6 +890,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks { PixelFormat.TRANSLUCENT); lp.token = new Binder(); lp.setTitle("NavigationBar"); + lp.accessibilityTitle = context.getString(R.string.nav_bar); lp.windowAnimations = 0; View navigationBarView = LayoutInflater.from(context).inflate( 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 d15c771ec098..63f2cebb61cc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java @@ -131,6 +131,9 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture mNavigationBarView.requestUnbufferedDispatch(event); event.transform(mTransformGlobalMatrix); try { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + overviewProxy.onPreMotionEvent(mNavigationBarView.getDownHitTarget()); + } overviewProxy.onMotionEvent(event); if (DEBUG_OVERVIEW_PROXY) { Log.d(TAG_OPS, "Send MotionEvent: " + event.toString()); @@ -146,8 +149,8 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture } public boolean onInterceptTouchEvent(MotionEvent event) { - int action = event.getAction(); - switch (action & MotionEvent.ACTION_MASK) { + int action = event.getActionMasked(); + switch (action) { case MotionEvent.ACTION_DOWN: { mTouchDownX = (int) event.getX(); mTouchDownY = (int) event.getY(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java index 9d20e4e1bb87..989423530599 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java @@ -57,13 +57,12 @@ public class NavigationBarInflaterView extends FrameLayout public static final String NAV_BAR_LEFT = "sysui_nav_bar_left"; public static final String NAV_BAR_RIGHT = "sysui_nav_bar_right"; - public static final String MENU_IME = "menu_ime"; + public static final String MENU_IME_ROTATE = "menu_ime"; public static final String BACK = "back"; public static final String HOME = "home"; public static final String RECENT = "recent"; public static final String NAVSPACE = "space"; public static final String CLIPBOARD = "clipboard"; - public static final String ROTATE = "rotate"; public static final String KEY = "key"; public static final String LEFT = "left"; public static final String RIGHT = "right"; @@ -317,10 +316,10 @@ public class NavigationBarInflaterView extends FrameLayout View v = null; String button = extractButton(buttonSpec); if (LEFT.equals(button)) { - String s = Dependency.get(TunerService.class).getValue(NAV_BAR_LEFT, ROTATE); + String s = Dependency.get(TunerService.class).getValue(NAV_BAR_LEFT, NAVSPACE); button = extractButton(s); } else if (RIGHT.equals(button)) { - String s = Dependency.get(TunerService.class).getValue(NAV_BAR_RIGHT, MENU_IME); + String s = Dependency.get(TunerService.class).getValue(NAV_BAR_RIGHT, MENU_IME_ROTATE); button = extractButton(s); } // Let plugins go first so they can override a standard view if they want. @@ -334,14 +333,12 @@ public class NavigationBarInflaterView extends FrameLayout v = inflater.inflate(R.layout.back, parent, false); } else if (RECENT.equals(button)) { v = inflater.inflate(R.layout.recent_apps, parent, false); - } else if (MENU_IME.equals(button)) { + } else if (MENU_IME_ROTATE.equals(button)) { v = inflater.inflate(R.layout.menu_ime, parent, false); } else if (NAVSPACE.equals(button)) { v = inflater.inflate(R.layout.nav_key_space, parent, false); } else if (CLIPBOARD.equals(button)) { v = inflater.inflate(R.layout.clipboard, parent, false); - } else if (ROTATE.equals(button)) { - v = inflater.inflate(R.layout.rotate_suggestion, parent, false); } else if (button.startsWith(KEY)) { String uri = extractImage(button); int code = extractKeycode(button); 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 af0afbdd6782..53dc814726a2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -16,6 +16,13 @@ package com.android.systemui.statusbar.phone; +import static android.view.MotionEvent.ACTION_DOWN; +import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK; +import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME; +import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; import android.animation.LayoutTransition.TransitionListener; import android.animation.ObjectAnimator; @@ -29,6 +36,7 @@ import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Point; import android.graphics.Rect; +import android.graphics.drawable.AnimatedVectorDrawable; import android.os.Handler; import android.os.Message; import android.os.RemoteException; @@ -49,6 +57,7 @@ import android.widget.FrameLayout; import com.android.settingslib.Utils; import com.android.systemui.Dependency; import com.android.systemui.DockedStackExistsListener; +import com.android.systemui.Interpolators; import com.android.systemui.OverviewProxyService; import com.android.systemui.R; import com.android.systemui.RecentsComponent; @@ -57,6 +66,7 @@ import com.android.systemui.plugins.PluginManager; import com.android.systemui.plugins.statusbar.phone.NavGesture; import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper; import com.android.systemui.recents.RecentsOnboarding; +import com.android.systemui.shared.system.NavigationBarCompat; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.policy.DeadZone; import com.android.systemui.statusbar.policy.KeyButtonDrawable; @@ -70,6 +80,8 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav final static boolean DEBUG = false; final static String TAG = "StatusBar/NavBarView"; + final static int BUTTON_FADE_IN_OUT_DURATION_MS = 100; + // slippery nav bar when everything is disabled, e.g. during setup final static boolean SLIPPERY_WHEN_DISABLED = true; @@ -85,9 +97,15 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav boolean mShowMenu; boolean mShowAccessibilityButton; boolean mLongClickableAccessibilityButton; + boolean mShowRotateButton; int mDisabledFlags = 0; int mNavigationIconHints = 0; + private @NavigationBarCompat.HitTarget int mDownHitTarget = HIT_TARGET_NONE; + private Rect mHomeButtonBounds = new Rect(); + private Rect mBackButtonBounds = new Rect(); + private int[] mTmpPosition = new int[2]; + private KeyButtonDrawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon; private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon; private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon; @@ -127,6 +145,8 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav private RecentsOnboarding mRecentsOnboarding; private NotificationPanelView mPanelView; + private Animator mRotateHideAnimator; + private class NavTransitionListener implements TransitionListener { private boolean mBackTransitioning; private boolean mHomeAppearing; @@ -217,6 +237,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav mShowAccessibilityButton = false; mLongClickableAccessibilityButton = false; + mOverviewProxyService = Dependency.get(OverviewProxyService.class); + mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService); + mConfiguration = new Configuration(); mConfiguration.updateFrom(context.getResources().getConfiguration()); updateIcons(context, Configuration.EMPTY, mConfiguration); @@ -232,9 +255,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav new ButtonDispatcher(R.id.accessibility_button)); mButtonDispatchers.put(R.id.rotate_suggestion, new ButtonDispatcher(R.id.rotate_suggestion)); - - mOverviewProxyService = Dependency.get(OverviewProxyService.class); - mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService); } public BarTransitions getBarTransitions() { @@ -275,6 +295,18 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav @Override public boolean onInterceptTouchEvent(MotionEvent event) { + switch (event.getActionMasked()) { + case ACTION_DOWN: + int x = (int) event.getX(); + int y = (int) event.getY(); + mDownHitTarget = HIT_TARGET_NONE; + if (mBackButtonBounds.contains(x, y)) { + mDownHitTarget = HIT_TARGET_BACK; + } else if (mHomeButtonBounds.contains(x, y)) { + mDownHitTarget = HIT_TARGET_HOME; + } + break; + } return mGestureHelper.onInterceptTouchEvent(event); } @@ -286,6 +318,10 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav return super.onTouchEvent(event); } + public @NavigationBarCompat.HitTarget int getDownHitTarget() { + return mDownHitTarget; + } + public void abortCurrentGesture() { getHomeButton().abortCurrentGesture(); } @@ -355,14 +391,23 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } if (oldConfig.densityDpi != newConfig.densityDpi || oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) { - mBackIcon = getDrawable(ctx, R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_dark); + final boolean proxyAvailable = mOverviewProxyService.getProxy() != null; + mBackIcon = proxyAvailable + ? getDrawable(ctx, R.drawable.ic_sysbar_back_quick_step, + R.drawable.ic_sysbar_back_quick_step_dark) + : getDrawable(ctx, R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_dark); mBackLandIcon = mBackIcon; - mBackAltIcon = getDrawable(ctx, - R.drawable.ic_sysbar_back_ime, R.drawable.ic_sysbar_back_ime_dark); + mBackAltIcon = proxyAvailable + ? getDrawable(ctx, R.drawable.ic_sysbar_back_ime_quick_step, + R.drawable.ic_sysbar_back_ime_quick_step_dark) + : getDrawable(ctx, R.drawable.ic_sysbar_back_ime, + R.drawable.ic_sysbar_back_ime_dark); mBackAltLandIcon = mBackAltIcon; - mHomeDefaultIcon = getDrawable(ctx, - R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark); + mHomeDefaultIcon = proxyAvailable + ? getDrawable(ctx, R.drawable.ic_sysbar_home_quick_step, + R.drawable.ic_sysbar_home_quick_step_dark) + : getDrawable(ctx, R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark); mRecentIcon = getDrawable(ctx, R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark); mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark); @@ -462,22 +507,25 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav getHomeButton().setImageDrawable(mHomeDefaultIcon); } - // The Accessibility button always overrides the appearance of the IME switcher + // Update IME button visibility, a11y and rotate button always overrides the appearance final boolean showImeButton = - !mShowAccessibilityButton && ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) - != 0); + !mShowAccessibilityButton && + !mShowRotateButton && + ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0); getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE); getImeSwitchButton().setImageDrawable(mImeIcon); - // Update menu button in case the IME state has changed. + // Update menu button, visibility logic in method setMenuVisibility(mShowMenu, true); getMenuButton().setImageDrawable(mMenuIcon); + // Update rotate button, visibility altered by a11y button logic + getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon); + + // Update a11y button, visibility logic in state method setAccessibilityButtonState(mShowAccessibilityButton, mLongClickableAccessibilityButton); getAccessibilityButton().setImageDrawable(mAccessibilityIcon); - getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon); - setDisabledFlags(mDisabledFlags, true); mBarTransitions.reapplyDarkIntensity(); @@ -621,8 +669,10 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav mShowMenu = show; - // Only show Menu if IME switcher and Accessibility button not shown. - final boolean shouldShow = mShowMenu && !mShowAccessibilityButton && + // Only show Menu if IME switcher, rotate and Accessibility buttons are not shown. + final boolean shouldShow = mShowMenu && + !mShowAccessibilityButton && + !mShowRotateButton && ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0); getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE); @@ -632,15 +682,96 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav mShowAccessibilityButton = visible; mLongClickableAccessibilityButton = longClickable; if (visible) { - // Accessibility button overrides Menu and IME switcher buttons. + // Accessibility button overrides Menu, IME switcher and rotate buttons. setMenuVisibility(false, true); getImeSwitchButton().setVisibility(View.INVISIBLE); + setRotateSuggestionButtonState(false, true); } getAccessibilityButton().setVisibility(visible ? View.VISIBLE : View.INVISIBLE); getAccessibilityButton().setLongClickable(longClickable); } + public void setRotateSuggestionButtonState(final boolean visible) { + setRotateSuggestionButtonState(visible, false); + } + + public void setRotateSuggestionButtonState(final boolean visible, final boolean force) { + ButtonDispatcher rotBtn = getRotateSuggestionButton(); + final boolean currentlyVisible = mShowRotateButton; + + // Rerun a show animation to indicate change but don't rerun a hide animation + if (!visible && !currentlyVisible) return; + + View currentView = rotBtn.getCurrentView(); + if (currentView == null) return; + + KeyButtonDrawable kbd = rotBtn.getImageDrawable(); + if (kbd == null) return; + + AnimatedVectorDrawable animIcon = null; + if (kbd.getDrawable(0) instanceof AnimatedVectorDrawable) { + animIcon = (AnimatedVectorDrawable) kbd.getDrawable(0); + } + + if (visible) { // Appear and change, cannot force + setRotateButtonVisibility(true); + + // Stop any currently running hide animations + if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) { + mRotateHideAnimator.pause(); + } + + // Reset the alpha if any has changed due to hide animation + currentView.setAlpha(1f); + + // Run the rotate icon's animation if it has one + if (animIcon != null) { + animIcon.reset(); + animIcon.start(); + } + + } else { // Hide + if (force) { + // If a hide animator is running stop it and instantly make invisible + if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) { + mRotateHideAnimator.pause(); + } + setRotateButtonVisibility(false); + return; + } + + // Don't start any new hide animations if one is running + if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) return; + + ObjectAnimator fadeOut = ObjectAnimator.ofFloat(currentView, "alpha", + 0f); + fadeOut.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS); + fadeOut.setInterpolator(Interpolators.LINEAR); + fadeOut.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + setRotateButtonVisibility(false); + } + }); + + mRotateHideAnimator = fadeOut; + fadeOut.start(); + } + } + + private void setRotateButtonVisibility(final boolean visible) { + // Never show if a11y is visible + final boolean adjVisible = visible && !mShowAccessibilityButton; + final int vis = adjVisible ? View.VISIBLE : View.INVISIBLE; + + getRotateSuggestionButton().setVisibility(vis); + mShowRotateButton = visible; + + // Hide/restore other button visibility, if necessary + setNavigationIconHints(mNavigationIconHints, true); + } + @Override public void onFinishInflate() { mNavigationInflaterView = (NavigationBarInflaterView) findViewById( @@ -666,6 +797,8 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav setSlippery(!isConnected); setDisabledFlags(mDisabledFlags, true); setUpSwipeUpOnboarding(isConnected); + updateIcons(getContext(), Configuration.EMPTY, mConfiguration); + setNavigationIconHints(mNavigationIconHints, true); } @Override @@ -677,9 +810,23 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); + updateButtonLocationOnScreen(getBackButton(), mBackButtonBounds); + updateButtonLocationOnScreen(getHomeButton(), mHomeButtonBounds); mGestureHelper.onLayout(changed, left, top, right, bottom); } + private void updateButtonLocationOnScreen(ButtonDispatcher button, Rect buttonBounds) { + View view = button.getCurrentView(); + if (view == null) { + buttonBounds.setEmpty(); + return; + } + view.getLocationInWindow(mTmpPosition); + buttonBounds.set(mTmpPosition[0], mTmpPosition[1], + mTmpPosition[0] + view.getMeasuredWidth(), + mTmpPosition[1] + view.getMeasuredHeight()); + } + private void updateRotatedViews() { mRotatedViews[Surface.ROTATION_0] = mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 0e8fcbabf2ae..3b129fc5e08d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -501,7 +501,8 @@ public class NotificationPanelView extends PanelView implements float shelfSize = shelf.getVisibility() == GONE ? 0 : shelf.getIntrinsicHeight() + notificationPadding; float availableSpace = mNotificationStackScroller.getHeight() - minPadding - shelfSize - - Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding); + - Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding) + - mKeyguardStatusView.getLogoutButtonHeight(); int count = 0; for (int i = 0; i < mNotificationStackScroller.getChildCount(); i++) { ExpandableView child = (ExpandableView) mNotificationStackScroller.getChildAt(i); 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 dc0835e4371a..bb2f59718ffb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java @@ -53,6 +53,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT; import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM; import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY; import static com.android.systemui.OverviewProxyService.TAG_OPS; +import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME; /** * Class to detect gestures on the navigation bar and implement quick scrub and switch. @@ -92,7 +93,6 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene private final Handler mHandler = new Handler(); private final Interpolator mQuickScrubEndInterpolator = new DecelerateInterpolator(); private final Rect mTrackRect = new Rect(); - private final Rect mHomeButtonRect = new Rect(); private final Paint mTrackPaint = new Paint(); private final int mScrollTouchSlop; private final OverviewProxyService mOverviewEventSender; @@ -138,7 +138,7 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velX, float velY) { if (!isQuickScrubEnabled() || mQuickScrubActive || !mAllowQuickSwitch || - !mHomeButtonRect.contains(mTouchDownX, mTouchDownY)) { + mNavigationBarView.getDownHitTarget() != HIT_TARGET_HOME) { return false; } float velocityX = mIsRTL ? -velX : velX; @@ -226,7 +226,8 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene case MotionEvent.ACTION_DOWN: { int x = (int) event.getX(); int y = (int) event.getY(); - if (isQuickScrubEnabled() && mHomeButtonRect.contains(x, y)) { + if (isQuickScrubEnabled() + && mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME) { mTouchDownX = x; mTouchDownY = y; homeButton.setDelayTouchFeedback(true); @@ -346,17 +347,6 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene x2 = x1 + width / 2 - mTrackPadding; } mTrackRect.set(x1, y1, x2, y2); - - // Get the touch rect of the home button location - View homeView = mNavigationBarView.getHomeButton().getCurrentView(); - if (homeView != null) { - int[] globalHomePos = homeView.getLocationOnScreen(); - int[] globalNavBarPos = mNavigationBarView.getLocationOnScreen(); - int homeX = globalHomePos[0] - globalNavBarPos[0]; - int homeY = globalHomePos[1] - globalNavBarPos[1]; - mHomeButtonRect.set(homeX, homeY, homeX + homeView.getMeasuredWidth(), - homeY + homeView.getMeasuredHeight()); - } } @Override @@ -381,7 +371,7 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene } boolean isQuickScrubEnabled() { - return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", false); + return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", true); } private void startQuickScrub() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 14387631f64d..94ebc1bac2b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -138,7 +138,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, protected float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD; protected float mScrimBehindAlphaUnlocking = SCRIM_BEHIND_ALPHA_UNLOCKING; - private float mFraction; + // Assuming the shade is expanded during initialization + private float mExpansionFraction = 1f; private boolean mDarkenWhileDragging; protected boolean mAnimateChange; @@ -166,6 +167,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, private boolean mScreenBlankingCallbackCalled; private Callback mCallback; private boolean mWallpaperSupportsAmbientMode; + private boolean mScreenOn; // Scrim blanking callbacks private Choreographer.FrameCallback mPendingFrameCallback; @@ -251,6 +253,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, mCurrentBehindTint = state.getBehindTint(); mCurrentInFrontAlpha = state.getFrontAlpha(); mCurrentBehindAlpha = state.getBehindAlpha(); + applyExpansionToAlpha(); // Cancel blanking transitions that were pending before we requested a new state if (mPendingFrameCallback != null) { @@ -362,45 +365,50 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, * @param fraction From 0 to 1 where 0 means collapse and 1 expanded. */ public void setPanelExpansion(float fraction) { - if (mFraction != fraction) { - mFraction = fraction; - - if (mState == ScrimState.UNLOCKED) { - // Darken scrim as you pull down the shade when unlocked - float behindFraction = getInterpolatedFraction(); - behindFraction = (float) Math.pow(behindFraction, 0.8f); - mCurrentBehindAlpha = behindFraction * mScrimBehindAlphaKeyguard; - mCurrentInFrontAlpha = 0; - } else if (mState == ScrimState.KEYGUARD) { - if (mUpdatePending) { - return; - } + if (mExpansionFraction != fraction) { + mExpansionFraction = fraction; - // Either darken of make the scrim transparent when you - // pull down the shade - float interpolatedFract = getInterpolatedFraction(); - if (mDarkenWhileDragging) { - mCurrentBehindAlpha = MathUtils.lerp(mScrimBehindAlphaUnlocking, - mScrimBehindAlphaKeyguard, interpolatedFract); - mCurrentInFrontAlpha = (1f - interpolatedFract) * SCRIM_IN_FRONT_ALPHA_LOCKED; - } else { - mCurrentBehindAlpha = MathUtils.lerp(0 /* start */, mScrimBehindAlphaKeyguard, - interpolatedFract); - mCurrentInFrontAlpha = 0; - } - } else { + if (!(mState == ScrimState.UNLOCKED || mState == ScrimState.KEYGUARD)) { + return; + } + + applyExpansionToAlpha(); + + if (mUpdatePending) { return; } if (mPinnedHeadsUpCount != 0) { updateHeadsUpScrim(false); } - updateScrim(false /* animate */, mScrimInFront, mCurrentInFrontAlpha); updateScrim(false /* animate */, mScrimBehind, mCurrentBehindAlpha); } } + private void applyExpansionToAlpha() { + if (mState == ScrimState.UNLOCKED) { + // Darken scrim as you pull down the shade when unlocked + float behindFraction = getInterpolatedFraction(); + behindFraction = (float) Math.pow(behindFraction, 0.8f); + mCurrentBehindAlpha = behindFraction * mScrimBehindAlphaKeyguard; + mCurrentInFrontAlpha = 0; + } else if (mState == ScrimState.KEYGUARD) { + // Either darken of make the scrim transparent when you + // pull down the shade + float interpolatedFract = getInterpolatedFraction(); + if (mDarkenWhileDragging) { + mCurrentBehindAlpha = MathUtils.lerp(mScrimBehindAlphaUnlocking, + mScrimBehindAlphaKeyguard, interpolatedFract); + mCurrentInFrontAlpha = (1f - interpolatedFract) * SCRIM_IN_FRONT_ALPHA_LOCKED; + } else { + mCurrentBehindAlpha = MathUtils.lerp(0 /* start */, mScrimBehindAlphaKeyguard, + interpolatedFract); + mCurrentInFrontAlpha = 0; + } + } + } + /** * Keyguard and shade scrim opacity varies according to how many notifications are visible. * @param notificationCount Number of visible notifications. @@ -496,7 +504,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, } private float getInterpolatedFraction() { - float frac = mFraction; + float frac = mExpansionFraction; // let's start this 20% of the way down the screen frac = frac * 1.2f - 0.2f; if (frac <= 0) { @@ -785,10 +793,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, // Setting power states can happen after we push out the frame. Make sure we // stay fully opaque until the power state request reaches the lower levels. + final int delay = mScreenOn ? 16 : 500; if (DEBUG) { - Log.d(TAG, "Waiting for the screen to turn on..."); + Log.d(TAG, "Fading out scrims with delay: " + delay); } - getHandler().postDelayed(mBlankingTransitionRunnable, 500); + getHandler().postDelayed(mBlankingTransitionRunnable, delay); }; doOnTheNextFrame(mPendingFrameCallback); } @@ -825,7 +834,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, } else { alpha = 1.0f - mTopHeadsUpDragAmount; } - float expandFactor = (1.0f - mFraction); + float expandFactor = (1.0f - mExpansionFraction); expandFactor = Math.max(expandFactor, 0.0f); return alpha * expandFactor; } @@ -904,6 +913,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, * Interrupts blanking transitions once the display notifies that it's already on. */ public void onScreenTurnedOn() { + mScreenOn = true; final Handler handler = getHandler(); if (handler.hasCallbacks(mBlankingTransitionRunnable)) { if (DEBUG) { @@ -914,6 +924,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, } } + public void onScreenTurnedOff() { + mScreenOn = false; + } + public interface Callback { default void onStart() { } 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 458518c41c3a..3b63d6c39146 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -4413,6 +4413,7 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void onScreenTurnedOff() { mFalsingManager.onScreenOff(); + mScrimController.onScreenTurnedOff(); // If we pulse in from AOD, we turn the screen off first. However, updatingIsKeyguard // in that case destroys the HeadsUpManager state, so don't do it in that case. if (!isPulsing()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index c30f6339f8da..948f524bb188 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -106,6 +106,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D mLp.gravity = Gravity.TOP; mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; mLp.setTitle("StatusBar"); + mLp.accessibilityTitle = mContext.getString(R.string.status_bar); mLp.packageName = mContext.getPackageName(); mStatusBarView = statusBarView; mBarHeight = barHeight; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java index 1da50ad65d62..503a1b40bb0c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java @@ -36,6 +36,7 @@ import com.android.systemui.statusbar.stack.ViewState; public class StatusIconContainer extends AlphaOptimizedLinearLayout { private static final String TAG = "StatusIconContainer"; + private static final boolean DEBUG = false; private static final int MAX_ICONS = 5; private static final int MAX_DOTS = 3; @@ -94,7 +95,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout { int childCount = getChildCount(); // Underflow === don't show content until that index int firstUnderflowIndex = -1; - android.util.Log.d(TAG, "calculateIconTransitions: start=" + translationX); + if (DEBUG) android.util.Log.d(TAG, "calculateIconTransitions: start=" + translationX); //TODO: Dots for (int i = childCount - 1; i >= 0; i--) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index 9d1c1e8b4b77..98bebec8511e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -52,6 +52,7 @@ import com.android.systemui.Dependency; import com.android.systemui.OverviewProxyService; import com.android.systemui.R; import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface; +import com.android.systemui.shared.system.ActivityManagerWrapper; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK; @@ -269,11 +270,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface { if (doIt) { // If there was a pending remote recents animation, then we need to // cancel the animation now before we handle the button itself - try { - ActivityManager.getService().cancelRecentsAnimation(); - } catch (RemoteException e) { - Log.e(TAG, "Could not cancel recents animation", e); - } + ActivityManagerWrapper.getInstance().cancelRecentsAnimation(); sendEvent(KeyEvent.ACTION_UP, 0); sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); } else { diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java index 45abd456ea16..eb0c89b06528 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java @@ -18,7 +18,7 @@ import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_END; import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_START; import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_IMAGE_DELIM; -import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.MENU_IME; +import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.MENU_IME_ROTATE; import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAVSPACE; import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_LEFT; import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_RIGHT; @@ -29,24 +29,14 @@ import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.ext import android.annotation.Nullable; import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.res.Resources; import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Paint.FontMetricsInt; -import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.os.Bundle; import android.os.Handler; -import android.support.v14.preference.PreferenceFragment; -import android.support.v7.preference.DropDownPreference; import android.support.v7.preference.ListPreference; import android.support.v7.preference.Preference; import android.support.v7.preference.Preference.OnPreferenceChangeListener; -import android.support.v7.preference.Preference.OnPreferenceClickListener; -import android.support.v7.preference.PreferenceCategory; import android.text.SpannableStringBuilder; import android.text.style.ImageSpan; import android.util.Log; @@ -56,7 +46,6 @@ import android.widget.EditText; import com.android.systemui.Dependency; import com.android.systemui.R; -import com.android.systemui.statusbar.phone.NavigationBarInflaterView; import com.android.systemui.tuner.TunerService.Tunable; import java.util.ArrayList; @@ -100,7 +89,7 @@ public class NavBarTuner extends TunerPreferenceFragment { addPreferencesFromResource(R.xml.nav_bar_tuner); bindLayout((ListPreference) findPreference(LAYOUT)); bindButton(NAV_BAR_LEFT, NAVSPACE, LEFT); - bindButton(NAV_BAR_RIGHT, MENU_IME, RIGHT); + bindButton(NAV_BAR_RIGHT, MENU_IME_ROTATE, RIGHT); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index 43e16dbeaeed..47027935d8d7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -180,6 +180,7 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void transitionToUnlocked() { + mScrimController.setPanelExpansion(0f); mScrimController.transitionTo(ScrimState.UNLOCKED); mScrimController.finishAnimationsImmediately(); // Front scrim should be transparent @@ -197,6 +198,7 @@ public class ScrimControllerTest extends SysuiTestCase { public void transitionToUnlockedFromAod() { // Simulate unlock with fingerprint mScrimController.transitionTo(ScrimState.AOD); + mScrimController.setPanelExpansion(0f); mScrimController.finishAnimationsImmediately(); mScrimController.transitionTo(ScrimState.UNLOCKED); // Immediately tinted after the transition starts @@ -324,6 +326,23 @@ public class ScrimControllerTest extends SysuiTestCase { verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class)); } + @Test + public void testConservesExpansionOpacityAfterTransition() { + mScrimController.transitionTo(ScrimState.UNLOCKED); + mScrimController.setPanelExpansion(0.5f); + mScrimController.finishAnimationsImmediately(); + + final float expandedAlpha = mScrimBehind.getViewAlpha(); + + mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR); + mScrimController.finishAnimationsImmediately(); + mScrimController.transitionTo(ScrimState.UNLOCKED); + mScrimController.finishAnimationsImmediately(); + + Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back", + expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f); + } + private void assertScrimTint(ScrimView scrimView, boolean tinted) { final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT; final String name = scrimView == mScrimInFront ? "front" : "back"; diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto index 08fdb9775d0a..608970f59a66 100644 --- a/proto/src/system_messages.proto +++ b/proto/src/system_messages.proto @@ -204,6 +204,10 @@ message SystemMessage { // Package: android NOTE_USB_TETHER = 47; + // Inform that DND settings have changed on OS upgrade + // Package: android + NOTE_ZEN_UPGRADE = 48; + // ADD_NEW_IDS_ABOVE_THIS_LINE // Legacy IDs with arbitrary values appear below // Legacy IDs existed as stable non-conflicting constants prior to the O release @@ -253,6 +257,7 @@ message SystemMessage { // Notify the user about public volume state changes.. // Package: com.android.systemui + NOTE_STORAGE_PUBLIC = 0x53505542; // 1397773634 // Notify the user about private volume state changes. diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 6747be340d46..5e5eacb5c767 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -64,6 +64,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.NoSuchElementException; /** * Since phone process can be restarted, this class provides a centralized place @@ -90,6 +91,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { IBinder binder; + TelephonyRegistryDeathRecipient deathRecipient; + IPhoneStateListener callback; IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback; @@ -251,6 +254,21 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } }; + private class TelephonyRegistryDeathRecipient implements IBinder.DeathRecipient { + + private final IBinder binder; + + TelephonyRegistryDeathRecipient(IBinder binder) { + this.binder = binder; + } + + @Override + public void binderDied() { + if (DBG) log("binderDied " + binder); + remove(binder); + } + } + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -378,23 +396,14 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - Record r; synchronized (mRecords) { // register - find_and_add: { - IBinder b = callback.asBinder(); - final int N = mRecords.size(); - for (int i = 0; i < N; i++) { - r = mRecords.get(i); - if (b == r.binder) { - break find_and_add; - } - } - r = new Record(); - r.binder = b; - mRecords.add(r); - if (DBG) log("listen oscl: add new record"); + IBinder b = callback.asBinder(); + Record r = add(b); + + if (r == null) { + return; } r.onSubscriptionsChangedListenerCallback = callback; @@ -496,20 +505,11 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { synchronized (mRecords) { // register - Record r; - find_and_add: { - IBinder b = callback.asBinder(); - final int N = mRecords.size(); - for (int i = 0; i < N; i++) { - r = mRecords.get(i); - if (b == r.binder) { - break find_and_add; - } - } - r = new Record(); - r.binder = b; - mRecords.add(r); - if (DBG) log("listen: add new record"); + IBinder b = callback.asBinder(); + Record r = add(b); + + if (r == null) { + return; } r.callback = callback; @@ -697,16 +697,57 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { return record.canReadPhoneState ? mCallIncomingNumber[phoneId] : ""; } + private Record add(IBinder binder) { + Record r; + + synchronized (mRecords) { + final int N = mRecords.size(); + for (int i = 0; i < N; i++) { + r = mRecords.get(i); + if (binder == r.binder) { + // Already existed. + return r; + } + } + r = new Record(); + r.binder = binder; + r.deathRecipient = new TelephonyRegistryDeathRecipient(binder); + + try { + binder.linkToDeath(r.deathRecipient, 0); + } catch (RemoteException e) { + if (VDBG) log("LinkToDeath remote exception sending to r=" + r + " e=" + e); + // Binder already died. Return null. + return null; + } + + mRecords.add(r); + if (DBG) log("add new record"); + } + + return r; + } + private void remove(IBinder binder) { synchronized (mRecords) { final int recordCount = mRecords.size(); for (int i = 0; i < recordCount; i++) { - if (mRecords.get(i).binder == binder) { + Record r = mRecords.get(i); + if (r.binder == binder) { if (DBG) { - Record r = mRecords.get(i); - log("remove: binder=" + binder + "r.callingPackage" + r.callingPackage - + "r.callback" + r.callback); + log("remove: binder=" + binder + " r.callingPackage " + r.callingPackage + + " r.callback " + r.callback); } + + if (r.deathRecipient != null) { + try { + binder.unlinkToDeath(r.deathRecipient, 0); + } catch (NoSuchElementException e) { + if (VDBG) log("UnlinkToDeath NoSuchElementException sending to r=" + + r + " e=" + e); + } + } + mRecords.remove(i); return; } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 14404f5d4e4f..5fc43732b404 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1095,7 +1095,7 @@ public final class ActiveServices { active.mNumActive++; } r.isForeground = true; - StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.userId, r.shortName, + StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName, StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER); } r.postNotification(); @@ -1112,7 +1112,7 @@ public final class ActiveServices { decActiveForegroundAppLocked(smap, r); } r.isForeground = false; - StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.userId, r.shortName, + StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName, StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT); if (r.app != null) { mAm.updateLruProcessLocked(r.app, false, null); @@ -2538,7 +2538,7 @@ public final class ActiveServices { cancelForegroundNotificationLocked(r); if (r.isForeground) { decActiveForegroundAppLocked(smap, r); - StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.userId, r.shortName, + StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName, StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c958b6765358..e8b78394f901 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -38,7 +38,6 @@ import static android.app.ActivityManagerInternal.ASSIST_KEY_STRUCTURE; import static android.app.ActivityThread.PROC_START_SEQ_IDENT; import static android.app.AppOpsManager.OP_ASSIST_STRUCTURE; import static android.app.AppOpsManager.OP_NONE; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; @@ -454,7 +453,6 @@ import com.android.server.pm.Installer.InstallerException; import com.android.server.utils.PriorityDump; import com.android.server.vr.VrManagerInternal; import com.android.server.wm.PinnedStackWindowController; -import com.android.server.wm.RecentsAnimationController; import com.android.server.wm.WindowManagerService; import dalvik.system.VMRuntime; @@ -1908,6 +1906,9 @@ public class ActivityManagerService extends IActivityManager.Stub final ActivityManagerConstants mConstants; + // Encapsulates the global setting "hidden_api_blacklist_exemptions" + final HiddenApiBlacklist mHiddenApiBlacklist; + PackageManagerInternal mPackageManagerInt; // VoiceInteraction session ID that changes for each new request except when @@ -2825,6 +2826,42 @@ public class ActivityManagerService extends IActivityManager.Stub } } + /** + * Encapsulates the globla setting "hidden_api_blacklist_exemptions", including tracking the + * latest value via a content observer. + */ + static class HiddenApiBlacklist extends ContentObserver { + + private final Context mContext; + private boolean mBlacklistDisabled; + + public HiddenApiBlacklist(Handler handler, Context context) { + super(handler); + mContext = context; + } + + public void registerObserver() { + mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS), + false, + this); + update(); + } + + private void update() { + mBlacklistDisabled = "*".equals(Settings.Global.getString(mContext.getContentResolver(), + Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS)); + } + + boolean isDisabled() { + return mBlacklistDisabled; + } + + public void onChange(boolean selfChange) { + update(); + } + } + @VisibleForTesting public ActivityManagerService(Injector injector) { mInjector = injector; @@ -2859,6 +2896,7 @@ public class ActivityManagerService extends IActivityManager.Stub mLifecycleManager = null; mProcStartHandlerThread = null; mProcStartHandler = null; + mHiddenApiBlacklist = null; } // Note: This method is invoked on the main thread but may need to attach various @@ -3002,6 +3040,8 @@ public class ActivityManagerService extends IActivityManager.Stub } }; + mHiddenApiBlacklist = new HiddenApiBlacklist(mHandler, mContext); + Watchdog.getInstance().addMonitor(this); Watchdog.getInstance().addThread(mHandler); @@ -4090,10 +4130,10 @@ public class ActivityManagerService extends IActivityManager.Stub runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES; } - 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; + if (!app.info.isAllowedToUseHiddenApi() && !mHiddenApiBlacklist.isDisabled()) { + // This app is not allowed to use undocumented and private APIs, or blacklisting is + // enabled. Set up its runtime with the appropriate flag. + runtimeFlags |= Zygote.ENABLE_HIDDEN_API_CHECKS; } String invokeWith = null; @@ -4371,7 +4411,7 @@ public class ActivityManagerService extends IActivityManager.Stub "updateUsageStats: comp=" + component + "res=" + resumed); final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); StatsLog.write(StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED, - component.userId, component.realActivity.getPackageName(), + component.app.uid, component.realActivity.getPackageName(), component.realActivity.getShortClassName(), resumed ? StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__ACTIVITY__MOVE_TO_FOREGROUND : StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__ACTIVITY__MOVE_TO_BACKGROUND); @@ -14578,6 +14618,7 @@ public class ActivityManagerService extends IActivityManager.Stub NETWORK_ACCESS_TIMEOUT_MS, NETWORK_ACCESS_TIMEOUT_DEFAULT_MS); final boolean supportsLeanbackOnly = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK_ONLY); + mHiddenApiBlacklist.registerObserver(); // Transfer any global setting for forcing RTL layout, into a System Property SystemProperties.set(DEVELOPMENT_FORCE_RTL, forceRtl ? "1":"0"); @@ -18550,6 +18591,7 @@ public class ActivityManagerService extends IActivityManager.Stub final long myTotalPss = mi.getTotalPss(); final long myTotalSwapPss = mi.getTotalSwappedOutPss(); totalPss += myTotalPss; + totalSwapPss += myTotalSwapPss; nativeProcTotalPss += myTotalPss; MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")", diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index ef82f36fa79f..fba03774e5d9 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -43,7 +43,10 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** @@ -65,12 +68,13 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { // There is some accuracy error in wifi reports so allow some slop in the results. private static final long MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS = 750; - private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor( - (ThreadFactory) r -> { - Thread t = new Thread(r, "batterystats-worker"); - t.setPriority(Thread.NORM_PRIORITY); - return t; - }); + private final ScheduledExecutorService mExecutorService = + Executors.newSingleThreadScheduledExecutor( + (ThreadFactory) r -> { + Thread t = new Thread(r, "batterystats-worker"); + t.setPriority(Thread.NORM_PRIORITY); + return t; + }); private final Context mContext; private final BatteryStatsImpl mStats; @@ -85,8 +89,20 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { private String mCurrentReason = null; @GuardedBy("this") + private boolean mOnBattery; + + @GuardedBy("this") + private boolean mOnBatteryScreenOff; + + @GuardedBy("this") + private boolean mUseLatestStates = true; + + @GuardedBy("this") private final IntArray mUidsToRemove = new IntArray(); + @GuardedBy("this") + private Future<?> mWakelockChangesUpdate; + private final Object mWorkerLock = new Object(); @GuardedBy("mWorkerLock") @@ -157,6 +173,50 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { return null; } + @Override + public Future<?> scheduleCpuSyncDueToScreenStateChange( + boolean onBattery, boolean onBatteryScreenOff) { + synchronized (BatteryExternalStatsWorker.this) { + if (mCurrentFuture == null || (mUpdateFlags & UPDATE_CPU) == 0) { + mOnBattery = onBattery; + mOnBatteryScreenOff = onBatteryScreenOff; + mUseLatestStates = false; + } + return scheduleSyncLocked("screen-state", UPDATE_CPU); + } + } + + @Override + public Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis) { + if (mExecutorService.isShutdown()) { + return CompletableFuture.failedFuture(new IllegalStateException("worker shutdown")); + } + + if (mWakelockChangesUpdate != null) { + // If there's already a scheduled task, leave it as is if we're trying to re-schedule + // it again with a delay, otherwise cancel and re-schedule it. + if (delayMillis == 0) { + mWakelockChangesUpdate.cancel(false); + } else { + return mWakelockChangesUpdate; + } + } + + mWakelockChangesUpdate = mExecutorService.schedule(() -> { + scheduleSync("wakelock-change", UPDATE_CPU); + scheduleRunnable(() -> mStats.postBatteryNeedsCpuUpdateMsg()); + mWakelockChangesUpdate = null; + }, delayMillis, TimeUnit.MILLISECONDS); + return mWakelockChangesUpdate; + } + + @Override + public void cancelCpuSyncDueToWakelockChange() { + if (mWakelockChangesUpdate != null) { + mWakelockChangesUpdate.cancel(false); + } + } + public synchronized Future<?> scheduleWrite() { if (mExecutorService.isShutdown()) { return CompletableFuture.failedFuture(new IllegalStateException("worker shutdown")); @@ -204,14 +264,21 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { final int updateFlags; final String reason; final int[] uidsToRemove; + final boolean onBattery; + final boolean onBatteryScreenOff; + final boolean useLatestStates; synchronized (BatteryExternalStatsWorker.this) { updateFlags = mUpdateFlags; reason = mCurrentReason; uidsToRemove = mUidsToRemove.size() > 0 ? mUidsToRemove.toArray() : EmptyArray.INT; + onBattery = mOnBattery; + onBatteryScreenOff = mOnBatteryScreenOff; + useLatestStates = mUseLatestStates; mUpdateFlags = 0; mCurrentReason = null; mUidsToRemove.clear(); mCurrentFuture = null; + mUseLatestStates = true; } synchronized (mWorkerLock) { @@ -219,7 +286,8 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { Slog.d(TAG, "begin updateExternalStatsSync reason=" + reason); } try { - updateExternalStatsLocked(reason, updateFlags); + updateExternalStatsLocked(reason, updateFlags, onBattery, + onBatteryScreenOff, useLatestStates); } finally { if (DEBUG) { Slog.d(TAG, "end updateExternalStatsSync"); @@ -250,7 +318,8 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { }; @GuardedBy("mWorkerLock") - private void updateExternalStatsLocked(final String reason, int updateFlags) { + private void updateExternalStatsLocked(final String reason, int updateFlags, + boolean onBattery, boolean onBatteryScreenOff, boolean useLatestStates) { // We will request data from external processes asynchronously, and wait on a timeout. SynchronousResultReceiver wifiReceiver = null; SynchronousResultReceiver bluetoothReceiver = null; @@ -306,7 +375,14 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { reason, 0); if ((updateFlags & UPDATE_CPU) != 0) { - mStats.updateCpuTimeLocked(); + if (useLatestStates) { + onBattery = mStats.isOnBatteryLocked(); + onBatteryScreenOff = mStats.isOnBatteryScreenOffLocked(); + } + mStats.updateCpuTimeLocked(onBattery, onBatteryScreenOff); + } + + if ((updateFlags & UPDATE_ALL) != 0) { mStats.updateKernelWakelocksLocked(); mStats.updateKernelMemoryBandwidthLocked(); } diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index ea52782027ba..9d1adb23957b 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -1057,7 +1057,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub // to block such a low level service like BatteryService on external stats like WiFi. mWorker.scheduleRunnable(() -> { synchronized (mStats) { - final boolean onBattery = plugType == BatteryStatsImpl.BATTERY_PLUGGED_NONE; + final boolean onBattery = BatteryStatsImpl.isOnBattery(plugType, status); if (mStats.isOnBattery() == onBattery) { // The battery state has not changed, so we don't need to sync external // stats immediately. diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java index db4e09fb79b8..6dcf04193c8e 100644 --- a/services/core/java/com/android/server/am/RecentsAnimation.java +++ b/services/core/java/com/android/server/am/RecentsAnimation.java @@ -28,7 +28,9 @@ import android.app.ActivityOptions; import android.content.ComponentName; import android.content.Intent; import android.os.Handler; +import android.os.RemoteException; import android.os.Trace; +import android.util.Slog; import android.view.IRecentsAnimationRunner; import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks; import com.android.server.wm.WindowManagerService; @@ -63,6 +65,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks { mHandler = new Handler(mStackSupervisor.mLooper); mWindowManager = wm; mUserController = userController; + mCancelAnimationRunnable = () -> { // The caller has not finished the animation in a predefined amount of time, so // force-cancel the animation @@ -73,13 +76,33 @@ class RecentsAnimation implements RecentsAnimationCallbacks { void startRecentsActivity(Intent intent, IRecentsAnimationRunner recentsAnimationRunner, ComponentName recentsComponent, int recentsUid) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity"); + + if (!mWindowManager.canStartRecentsAnimation()) { + notifyAnimationCancelBeforeStart(recentsAnimationRunner); + return; + } + + // If the existing home activity is already on top, then cancel + ActivityRecord homeActivity = mStackSupervisor.getHomeActivity(); + final boolean hasExistingHomeActivity = homeActivity != null; + if (hasExistingHomeActivity) { + final ActivityDisplay display = homeActivity.getDisplay(); + mRestoreHomeBehindStack = display.getStackAboveHome(); + if (mRestoreHomeBehindStack == null) { + notifyAnimationCancelBeforeStart(recentsAnimationRunner); + return; + } + } + mWindowManager.deferSurfaceLayout(); try { - // Cancel the previous recents animation if necessary - mWindowManager.cancelRecentsAnimation(); - final boolean hasExistingHomeActivity = mStackSupervisor.getHomeActivity() != null; - if (!hasExistingHomeActivity) { + final ActivityDisplay display; + if (hasExistingHomeActivity) { + // Move the home activity into place for the animation if it is not already top most + display = homeActivity.getDisplay(); + display.moveHomeStackBehindBottomMostVisibleStack(); + } else { // No home activity final ActivityOptions opts = ActivityOptions.makeBasic(); opts.setLaunchActivityType(ACTIVITY_TYPE_HOME); @@ -95,25 +118,20 @@ class RecentsAnimation implements RecentsAnimationCallbacks { .execute(); mWindowManager.prepareAppTransition(TRANSIT_NONE, false); + homeActivity = mStackSupervisor.getHomeActivity(); + display = homeActivity.getDisplay(); + // TODO: Maybe wait for app to draw in this particular case? } - final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity(); - final ActivityDisplay display = homeActivity.getDisplay(); - - // Save the initial position of the home activity stack to be restored to after the - // animation completes - mRestoreHomeBehindStack = hasExistingHomeActivity - ? display.getStackAboveHome() - : null; - - // Move the home activity into place for the animation - display.moveHomeStackBehindBottomMostVisibleStack(); - // Mark the home activity as launch-behind to bump its visibility for the // duration of the gesture that is driven by the recents component homeActivity.mLaunchTaskBehind = true; + // Post a timeout for the animation. This needs to happen before initializing the + // recents animation on the WM side since we may decide to cancel the animation there + mHandler.postDelayed(mCancelAnimationRunnable, RECENTS_ANIMATION_TIMEOUT); + // Fetch all the surface controls and pass them to the client to get the animation // started mWindowManager.initializeRecentsAnimation(recentsAnimationRunner, this, @@ -122,9 +140,6 @@ class RecentsAnimation implements RecentsAnimationCallbacks { // If we updated the launch-behind state, update the visibility of the activities after // we fetch the visible tasks to be controlled by the animation mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS); - - // Post a timeout for the animation - mHandler.postDelayed(mCancelAnimationRunnable, RECENTS_ANIMATION_TIMEOUT); } finally { mWindowManager.continueSurfaceLayout(); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); @@ -178,4 +193,15 @@ class RecentsAnimation implements RecentsAnimationCallbacks { }); } } + + /** + * Called only when the animation should be canceled prior to starting. + */ + private void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) { + try { + recentsAnimationRunner.onAnimationCanceled(); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to cancel recents animation before start", e); + } + } } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index e95608f16203..fffe7dca7fc4 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -70,6 +70,7 @@ import android.media.AudioRoutesInfo; import android.media.AudioSystem; import android.media.IAudioFocusDispatcher; import android.media.IAudioRoutesObserver; +import android.media.IAudioServerStateDispatcher; import android.media.IAudioService; import android.media.IPlaybackConfigDispatcher; import android.media.IRecordingConfigDispatcher; @@ -242,6 +243,7 @@ public class AudioService extends IAudioService.Stub private static final int MSG_INDICATE_SYSTEM_READY = 26; private static final int MSG_ACCESSORY_PLUG_MEDIA_UNMUTE = 27; private static final int MSG_NOTIFY_VOL_EVENT = 28; + private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 29; // start of messages handled under wakelock // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) @@ -390,6 +392,8 @@ public class AudioService extends IAudioService.Stub case AudioSystem.AUDIO_STATUS_SERVER_DIED: sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0, null, 0); + sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE, + SENDMSG_QUEUE, 0, 0, null, 0); break; default: break; @@ -1000,6 +1004,21 @@ public class AudioService extends IAudioService.Stub onIndicateSystemReady(); // indicate the end of reconfiguration phase to audio HAL AudioSystem.setParameters("restarting=false"); + + sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE, + SENDMSG_QUEUE, 1, 0, null, 0); + } + + private void onDispatchAudioServerStateChange(boolean state) { + synchronized (mAudioServerStateListeners) { + for (AsdProxy asdp : mAudioServerStateListeners.values()) { + try { + asdp.callback().dispatchAudioServerStateChange(state); + } catch (RemoteException e) { + Log.w(TAG, "Could not call dispatchAudioServerStateChange()", e); + } + } + } } private void createAudioSystemThread() { @@ -5089,6 +5108,10 @@ public class AudioService extends IAudioService.Stub onAudioServerDied(); break; + case MSG_DISPATCH_AUDIO_SERVER_STATE: + onDispatchAudioServerStateChange(msg.arg1 == 1); + break; + case MSG_UNLOAD_SOUND_EFFECTS: onUnloadSoundEffects(); break; @@ -7341,6 +7364,77 @@ public class AudioService extends IAudioService.Stub //====================== + // Audioserver state displatch + //====================== + private class AsdProxy implements IBinder.DeathRecipient { + private final IAudioServerStateDispatcher mAsd; + + AsdProxy(IAudioServerStateDispatcher asd) { + mAsd = asd; + } + + public void binderDied() { + synchronized (mAudioServerStateListeners) { + mAudioServerStateListeners.remove(mAsd.asBinder()); + } + } + + IAudioServerStateDispatcher callback() { + return mAsd; + } + } + + private HashMap<IBinder, AsdProxy> mAudioServerStateListeners = + new HashMap<IBinder, AsdProxy>(); + + private void checkMonitorAudioServerStatePermission() { + if (!(mContext.checkCallingOrSelfPermission( + android.Manifest.permission.MODIFY_PHONE_STATE) == + PackageManager.PERMISSION_GRANTED || + mContext.checkCallingOrSelfPermission( + android.Manifest.permission.MODIFY_AUDIO_ROUTING) == + PackageManager.PERMISSION_GRANTED)) { + throw new SecurityException("Not allowed to monitor audioserver state"); + } + } + + public void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd) { + checkMonitorAudioServerStatePermission(); + synchronized (mAudioServerStateListeners) { + if (mAudioServerStateListeners.containsKey(asd.asBinder())) { + Slog.w(TAG, "Cannot re-register audio server state dispatcher"); + return; + } + AsdProxy asdp = new AsdProxy(asd); + try { + asd.asBinder().linkToDeath(asdp, 0/*flags*/); + } catch (RemoteException e) { + + } + mAudioServerStateListeners.put(asd.asBinder(), asdp); + } + } + + public void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd) { + checkMonitorAudioServerStatePermission(); + synchronized (mAudioServerStateListeners) { + AsdProxy asdp = mAudioServerStateListeners.remove(asd.asBinder()); + if (asdp == null) { + Slog.w(TAG, "Trying to unregister unknown audioserver state dispatcher for pid " + + Binder.getCallingPid() + " / uid " + Binder.getCallingUid()); + return; + } else { + asd.asBinder().unlinkToDeath(asdp, 0/*flags*/); + } + } + } + + public boolean isAudioServerRunning() { + checkMonitorAudioServerStatePermission(); + return (AudioSystem.checkAudioFlinger() == AudioSystem.AUDIO_STATUS_OK); + } + + //====================== // misc //====================== private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies = diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index b8771849ac71..21d86c452a8e 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -29,6 +29,7 @@ import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; @@ -76,6 +77,7 @@ import android.util.SparseIntArray; import android.view.KeyEvent; import android.view.ViewConfiguration; +import com.android.internal.os.BackgroundThread; import com.android.internal.util.DumpUtils; import com.android.server.SystemService; import com.android.server.Watchdog; @@ -180,9 +182,8 @@ public class MediaSessionService extends SystemService implements Monitor { updateUser(); + registerPackageBroadcastReceivers(); // TODO(jaewan): Query per users - // TODO(jaewan): Add listener to know changes in list of services. - // Refer TvInputManagerService.registerBroadcastReceivers() buildMediaSessionService2List(); } @@ -437,12 +438,74 @@ public class MediaSessionService extends SystemService implements Monitor { mHandler.postSessionsChanged(session.getUserId()); } + private void registerPackageBroadcastReceivers() { + // TODO(jaewan): Only consider changed packages when building session service list + // when we make this multi-user aware. At that time, + // use PackageMonitor.getChangingUserId() to know which user has changed. + IntentFilter filter = new IntentFilter(); + filter.addDataScheme("package"); + filter.addAction(Intent.ACTION_PACKAGE_ADDED); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addAction(Intent.ACTION_PACKAGES_SUSPENDED); + filter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED); + filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); + filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); + filter.addAction(Intent.ACTION_PACKAGE_REPLACED); + + getContext().registerReceiverAsUser(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final int changeUserId = intent.getIntExtra( + Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); + if (changeUserId == UserHandle.USER_NULL) { + Log.w(TAG, "Intent broadcast does not contain user handle: "+ intent); + return; + } + // Check if the package is replacing (i.e. reinstalling) + final boolean isReplacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); + // TODO(jaewan): Add multi-user support with this. + // final int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); + + if (DEBUG) { + Log.d(TAG, "Received change in packages, intent=" + intent); + } + switch (intent.getAction()) { + case Intent.ACTION_PACKAGE_ADDED: + case Intent.ACTION_PACKAGE_REMOVED: + case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE: + case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE: + if (isReplacing) { + // Ignore if the package(s) are replacing. In that case, followings will + // happen in order. + // 1. ACTION_PACKAGE_REMOVED with isReplacing=true + // 2. ACTION_PACKAGE_ADDED with isReplacing=true + // 3. ACTION_PACKAGE_REPLACED + // (Note that ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE and + // ACTION_EXTERNAL_APPLICATIONS_AVAILABLE will be also called with + // isReplacing=true for both ASEC hosted packages and packages in + // external storage) + // Since we only want to update session service list once, ignore + // actions above when replacing. + // Replacing will be handled only once with the ACTION_PACKAGE_REPLACED. + break; + } + // pass-through + case Intent.ACTION_PACKAGE_CHANGED: + case Intent.ACTION_PACKAGES_SUSPENDED: + case Intent.ACTION_PACKAGES_UNSUSPENDED: + case Intent.ACTION_PACKAGE_REPLACED: + buildMediaSessionService2List(); + } + } + }, UserHandle.ALL, filter, null, BackgroundThread.getHandler()); + } + private void buildMediaSessionService2List() { if (DEBUG) { Log.d(TAG, "buildMediaSessionService2List"); } - - // TODO(jaewan): Query per users. + // TODO(jaewan): Also query for managed profile users. // TODO(jaewan): Similar codes are also at the updatable. Can't we share codes? PackageManager manager = getContext().getPackageManager(); List<ResolveInfo> services = new ArrayList<>(); @@ -458,9 +521,13 @@ public class MediaSessionService extends SystemService implements Monitor { services.addAll(sessionServices); } synchronized (mLock) { - mSessions.clear(); - if (services == null) { - return; + // List to keep the session services that need be removed because they don't exist + // in the 'services' above. + List<MediaSession2Record> removeCandidates = new ArrayList<>(); + for (int i = 0; i < mSessions.size(); i++) { + if (mSessions.get(i).getToken().getType() != TYPE_SESSION) { + removeCandidates.add(mSessions.get(i)); + } } for (int i = 0; i < services.size(); i++) { if (services.get(i) == null || services.get(i).serviceInfo == null) { @@ -475,17 +542,35 @@ public class MediaSessionService extends SystemService implements Monitor { } catch (NameNotFoundException e) { continue; } - + SessionToken2 token; try { - SessionToken2 token = new SessionToken2(getContext(), + token = new SessionToken2(getContext(), serviceInfo.packageName, serviceInfo.name, uid); + } catch (IllegalArgumentException e) { + Log.w(TAG, "Invalid session service", e); + continue; + } + boolean found = false; + for (int j = 0; j < mSessions.size(); j++) { + if (token.equals(mSessions.get(j).getToken())) { + // If the token already exists, keep it in the mSessions. + removeCandidates.remove(mSessions.get(j)); + found = true; + break; + } + } + if (!found) { + // New session service is found. MediaSession2Record record = new MediaSession2Record(getContext(), token, mSessionDestroyedListener); mSessions.add(record); - } catch (IllegalArgumentException e) { - Log.d(TAG, "Invalid session service", e); } } + for (int i = 0; i < removeCandidates.size(); i++) { + removeCandidates.get(i).onSessionDestroyed(); + mSessions.remove(removeCandidates.get(i)); + } + removeCandidates.clear(); } if (DEBUG) { Log.d(TAG, "Found " + mSessions.size() + " session services"); @@ -1503,12 +1588,14 @@ public class MediaSessionService extends SystemService implements Monitor { return tokens; } + // TODO(jaewan): Protect this API with permission @Override public void addSessionTokensListener(ISessionTokensListener listener, int userId, String packageName) { // TODO(jaewan): Implement. } + // TODO(jaewan): Protect this API with permission @Override public void removeSessionTokensListener(ISessionTokensListener listener) { // TODO(jaewan): Implement diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 7e3b5516b8cc..0a870978d160 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -18,8 +18,10 @@ package com.android.server.notification; import android.app.AppOpsManager; import android.app.AutomaticZenRule; +import android.app.Notification; import android.app.NotificationManager; import android.app.NotificationManager.Policy; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -44,6 +46,7 @@ import android.os.Message; import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; +import android.provider.Settings; import android.provider.Settings.Global; import android.service.notification.Condition; import android.service.notification.ConditionProviderService; @@ -61,6 +64,8 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; +import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; +import com.android.internal.notification.SystemNotificationChannels; import com.android.server.LocalServices; import libcore.io.IoUtils; @@ -89,6 +94,7 @@ public class ZenModeHelper { private final H mHandler; private final SettingsObserver mSettingsObserver; @VisibleForTesting protected final AppOpsManager mAppOps; + @VisibleForTesting protected final NotificationManager mNotificationManager; protected ZenModeConfig mDefaultConfig; private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); private final ZenModeFiltering mFiltering; @@ -112,12 +118,14 @@ public class ZenModeHelper { protected String mDefaultRuleEveryNightName; protected String mDefaultRuleEventsName; + @VisibleForTesting protected boolean mIsBootComplete; public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) { mContext = context; mHandler = new H(looper); addCallback(mMetrics); mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + mNotificationManager = context.getSystemService(NotificationManager.class); mDefaultConfig = new ZenModeConfig(); setDefaultZenRules(mContext); @@ -197,6 +205,8 @@ public class ZenModeHelper { mHandler.postMetricsTimer(); cleanUpZenRules(); evaluateZenMode("onSystemReady", true); + mIsBootComplete = true; + showZenUpgradeNotification(mZenMode); } public void onUserSwitched(int user) { @@ -612,6 +622,10 @@ public class ZenModeHelper { throws XmlPullParserException, IOException { final ZenModeConfig config = ZenModeConfig.readXml(parser); if (config != null) { + if (config.version < ZenModeConfig.XML_VERSION) { + Settings.Global.putInt(mContext.getContentResolver(), + Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1); + } if (forRestore) { //TODO: http://b/22388012 if (config.user != UserHandle.USER_SYSTEM) { @@ -755,8 +769,10 @@ public class ZenModeHelper { return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF); } - private void setZenModeSetting(int zen) { + @VisibleForTesting + protected void setZenModeSetting(int zen) { Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen); + showZenUpgradeNotification(zen); } private int getPreviousRingerModeSetting() { @@ -1139,6 +1155,41 @@ public class ZenModeHelper { } } + private void showZenUpgradeNotification(int zen) { + final boolean showNotification = mIsBootComplete + && zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS + && Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0; + + if (showNotification) { + mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE, + createZenUpgradeNotification()); + Settings.Global.putInt(mContext.getContentResolver(), + Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); + } + } + + @VisibleForTesting + protected Notification createZenUpgradeNotification() { + Intent intent = new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS) + .setPackage("com.android.settings") + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + final Bundle extras = new Bundle(); + extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, + mContext.getResources().getString(R.string.global_action_settings)); + return new Notification.Builder(mContext, SystemNotificationChannels.SYSTEM_CHANGES) + .setSmallIcon(R.drawable.ic_settings_24dp) + .setContentTitle(mContext.getResources().getString( + R.string.zen_upgrade_notification_title)) + .setContentText(mContext.getResources().getString( + R.string.zen_upgrade_notification_content)) + .setAutoCancel(true) + .setLocalOnly(true) + .addExtras(extras) + .setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0, null)) + .build(); + } + private final class Metrics extends Callback { private static final String COUNTER_PREFIX = "dnd_mode_"; private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000; diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index b79caca317a4..1746dd1a2b27 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -63,9 +63,8 @@ public class Installer extends SystemService { public static final int DEXOPT_STORAGE_DE = 1 << 8; /** Indicates that dexopt is invoked from the background service. */ public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9; - /* Indicates that dexopt should not restrict access to private APIs. - * Must be kept in sync with com.android.internal.os.ZygoteInit. */ - public static final int DEXOPT_DISABLE_HIDDEN_API_CHECKS = 1 << 10; + /** Indicates that dexopt should restrict access to private APIs. */ + public static final int DEXOPT_ENABLE_HIDDEN_API_CHECKS = 1 << 10; // NOTE: keep in sync with installd public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8; diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 2c68e67a3bd5..458d725db030 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -57,7 +57,7 @@ import static com.android.server.pm.Installer.DEXOPT_FORCE; import static com.android.server.pm.Installer.DEXOPT_STORAGE_CE; import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE; import static com.android.server.pm.Installer.DEXOPT_IDLE_BACKGROUND_JOB; -import static com.android.server.pm.Installer.DEXOPT_DISABLE_HIDDEN_API_CHECKS; +import static com.android.server.pm.Installer.DEXOPT_ENABLE_HIDDEN_API_CHECKS; import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; @@ -528,11 +528,9 @@ public class PackageDexOptimizer { boolean isPublic = !info.isForwardLocked() && (!isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata()); int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0; - // System apps are invoked with a runtime flag which exempts them from - // restrictions on hidden API usage. We dexopt with the same runtime flag - // otherwise offending methods would have to be re-verified at runtime - // and we want to avoid the performance overhead of that. - int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? DEXOPT_DISABLE_HIDDEN_API_CHECKS : 0; + // Some apps are executed with restrictions on hidden API usage. If this app is one + // of them, pass a flag to dexopt to enable the same restrictions during compilation. + int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? 0 : DEXOPT_ENABLE_HIDDEN_API_CHECKS; int dexFlags = (isPublic ? DEXOPT_PUBLIC : 0) | (debuggable ? DEXOPT_DEBUGGABLE : 0) @@ -655,8 +653,8 @@ public class PackageDexOptimizer { if ((flags & DEXOPT_IDLE_BACKGROUND_JOB) == DEXOPT_IDLE_BACKGROUND_JOB) { flagsList.add("idle_background_job"); } - if ((flags & DEXOPT_DISABLE_HIDDEN_API_CHECKS) == DEXOPT_DISABLE_HIDDEN_API_CHECKS) { - flagsList.add("disable_hidden_api_checks"); + if ((flags & DEXOPT_ENABLE_HIDDEN_API_CHECKS) == DEXOPT_ENABLE_HIDDEN_API_CHECKS) { + flagsList.add("enable_hidden_api_checks"); } return String.join(",", flagsList); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 0502848d698e..d9bcc5c92591 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -1326,30 +1326,38 @@ public class PhoneWindowManager implements WindowManagerPolicy { // When interactive, we're already awake. // Wait for a long press or for the button to be released to decide what to do. if (hasLongPressOnPowerBehavior()) { - Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); - msg.setAsynchronous(true); - mHandler.sendMessageDelayed(msg, - ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); + if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { + powerLongPress(); + } else { + Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); + msg.setAsynchronous(true); + mHandler.sendMessageDelayed(msg, + ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); - if (hasVeryLongPressOnPowerBehavior()) { - Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS); - longMsg.setAsynchronous(true); - mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout); + if (hasVeryLongPressOnPowerBehavior()) { + Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS); + longMsg.setAsynchronous(true); + mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout); + } } } } else { wakeUpFromPowerKey(event.getDownTime()); if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) { - Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); - msg.setAsynchronous(true); - mHandler.sendMessageDelayed(msg, - ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); + if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { + powerLongPress(); + } else { + Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); + msg.setAsynchronous(true); + mHandler.sendMessageDelayed(msg, + ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); - if (hasVeryLongPressOnPowerBehavior()) { - Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS); - longMsg.setAsynchronous(true); - mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout); + if (hasVeryLongPressOnPowerBehavior()) { + Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS); + longMsg.setAsynchronous(true); + mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout); + } } mBeganFromNonInteractive = true; diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index 4bc94047b24e..9f9b1af5397e 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -361,9 +361,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { if (DEBUG) Slog.d(TAG, "Setting anomaly alarm for " + timestampMs); final long callingToken = Binder.clearCallingIdentity(); try { - // using RTC, not RTC_WAKEUP, so if device is asleep, will only fire when it awakens. + // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will + // only fire when it awakens. + // This alarm is inexact, leaving its exactness completely up to the OS optimizations. // AlarmManager will automatically cancel any previous mAnomalyAlarmIntent alarm. - mAlarmManager.setExact(AlarmManager.RTC, timestampMs, mAnomalyAlarmIntent); + mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, mAnomalyAlarmIntent); } finally { Binder.restoreCallingIdentity(callingToken); } @@ -388,10 +390,12 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { Slog.d(TAG, "Setting pulling alarm for " + timestampMs + " every " + intervalMs + "ms"); final long callingToken = Binder.clearCallingIdentity(); try { - // using RTC, not RTC_WAKEUP, so if device is asleep, will only fire when it awakens. + // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will + // only fire when it awakens. // This alarm is inexact, leaving its exactness completely up to the OS optimizations. // TODO: totally inexact means that stats per bucket could be quite off. Is this okay? - mAlarmManager.setRepeating(AlarmManager.RTC, timestampMs, intervalMs, mPullingAlarmIntent); + mAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, timestampMs, intervalMs, + mPullingAlarmIntent); } finally { Binder.restoreCallingIdentity(callingToken); } diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java index db956344e5ac..3cd3e8b0912e 100644 --- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java +++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java @@ -53,8 +53,7 @@ class AppWindowThumbnail implements Animatable { AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader) { mAppToken = appToken; - mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, - appToken.mService.mAnimator::addAfterPrepareSurfacesRunnable, appToken.mService); + mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, appToken.mService); mWidth = thumbnailHeader.getWidth(); mHeight = thumbnailHeader.getHeight(); @@ -145,11 +144,6 @@ class AppWindowThumbnail implements Animatable { } @Override - public void destroyAfterPendingTransaction(SurfaceControl surface) { - mAppToken.destroyAfterPendingTransaction(surface); - } - - @Override public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) { t.setLayer(leash, Integer.MAX_VALUE); } diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java index 4394a99bc5c9..a180a3acfbed 100644 --- a/services/core/java/com/android/server/wm/Dimmer.java +++ b/services/core/java/com/android/server/wm/Dimmer.java @@ -55,11 +55,6 @@ class Dimmer { } @Override - public void destroyAfterPendingTransaction(SurfaceControl surface) { - mHost.destroyAfterPendingTransaction(surface); - } - - @Override public SurfaceControl.Builder makeAnimationLeash() { return mHost.makeAnimationLeash(); } @@ -119,7 +114,7 @@ class Dimmer { if (!mDimming) { mDimLayer.destroy(); } - }, mHost.mService.mAnimator::addAfterPrepareSurfacesRunnable, mHost.mService); + }, mHost.mService); } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 41a6e2ba7e69..f421bf46e84a 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -380,11 +380,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo */ private int mSurfaceSize; - /** - * A list of surfaces to be destroyed after {@link #mPendingTransaction} is applied. - */ - private final ArrayList<SurfaceControl> mPendingDestroyingSurfaces = new ArrayList<>(); - /** Temporary float array to retrieve 3x3 matrix values. */ private final float[] mTmpFloats = new float[9]; @@ -1935,10 +1930,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } mService.mAnimator.removeDisplayLocked(mDisplayId); - - // The pending transaction won't be applied so we should - // just clean up any surfaces pending destruction. - onPendingTransactionApplied(); } finally { mRemovingDisplay = false; } @@ -3847,22 +3838,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } @Override - public void destroyAfterPendingTransaction(SurfaceControl surface) { - mPendingDestroyingSurfaces.add(surface); - } - - /** - * Destroys any surfaces that have been put into the pending list with - * {@link #destroyAfterPendingTransaction}. - */ - void onPendingTransactionApplied() { - for (int i = mPendingDestroyingSurfaces.size() - 1; i >= 0; i--) { - mPendingDestroyingSurfaces.get(i).destroy(); - } - mPendingDestroyingSurfaces.clear(); - } - - @Override void prepareSurfaces() { final ScreenRotationAnimation screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); @@ -3876,6 +3851,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mPendingTransaction.setAlpha(mWindowingLayer, screenRotationAnimation.getEnterTransformation().getAlpha()); } + super.prepareSurfaces(); } } diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index e869f582ed1f..e4edeb877b70 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -24,15 +24,15 @@ import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_W import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; -import android.app.ActivityManager; import android.app.ActivityManager.TaskSnapshot; import android.app.WindowConfiguration; -import android.graphics.GraphicBuffer; import android.graphics.Point; import android.graphics.Rect; import android.os.Binder; +import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; +import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.view.IRecentsAnimationController; @@ -41,6 +41,7 @@ import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; +import com.google.android.collect.Sets; import java.io.PrintWriter; import java.util.ArrayList; @@ -59,6 +60,7 @@ public class RecentsAnimationController { private final IRecentsAnimationRunner mRunner; private final RecentsAnimationCallbacks mCallbacks; private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>(); + private final int mDisplayId; // The recents component app token that is shown behind the visibile tasks private AppWindowToken mHomeAppToken; @@ -98,17 +100,13 @@ public class RecentsAnimationController { final TaskAnimationAdapter adapter = mPendingAnimations.get(i); final Task task = adapter.mTask; if (task.mTaskId == taskId) { - // TODO: Save this screenshot as the task snapshot? - final Rect taskFrame = new Rect(); - task.getBounds(taskFrame); - final GraphicBuffer buffer = SurfaceControl.captureLayers( - task.getSurfaceControl().getHandle(), taskFrame, 1f); - final AppWindowToken topChild = task.getTopChild(); - final WindowState mainWindow = topChild.findMainWindow(); - return new TaskSnapshot(buffer, topChild.getConfiguration().orientation, - mainWindow.mContentInsets, - ActivityManager.isLowRamDeviceStatic() /* reduced */, - 1.0f /* scale */); + final TaskSnapshotController snapshotController = + mService.mTaskSnapshotController; + final ArraySet<Task> tasks = Sets.newArraySet(task); + snapshotController.snapshotTasks(tasks); + snapshotController.addSkipClosingAppSnapshotTasks(tasks); + return snapshotController.getSnapshot(taskId, 0 /* userId */, + false /* restoreFromDisk */, false /* reducedResolution */); } } return null; @@ -159,8 +157,6 @@ public class RecentsAnimationController { }; /** - * Initializes a new RecentsAnimationController. - * * @param remoteAnimationRunner The remote runner which should be notified when the animation is * ready to start or has been canceled * @param callbacks Callbacks to be made when the animation finishes @@ -171,16 +167,19 @@ public class RecentsAnimationController { mService = service; mRunner = remoteAnimationRunner; mCallbacks = callbacks; + mDisplayId = displayId; + } - final DisplayContent dc = mService.mRoot.getDisplayContent(displayId); - final ArrayList<Task> visibleTasks = dc.getVisibleTasks(); - if (visibleTasks.isEmpty()) { - cancelAnimation(); - return; - } - + /** + * Initializes the recents animation controller. This is a separate call from the constructor + * because it may call cancelAnimation() which needs to properly clean up the controller + * in the window manager. + */ + public void initialize() { // Make leashes for each of the visible tasks and add it to the recents animation to be // started + final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId); + final ArrayList<Task> visibleTasks = dc.getVisibleTasks(); final int taskCount = visibleTasks.size(); for (int i = 0; i < taskCount; i++) { final Task task = visibleTasks.get(i); @@ -193,6 +192,12 @@ public class RecentsAnimationController { addAnimation(task); } + // Skip the animation if there is nothing to animate + if (mPendingAnimations.isEmpty()) { + cancelAnimation(); + return; + } + // Adjust the wallpaper visibility for the showing home activity final AppWindowToken recentsComponentAppToken = dc.getHomeStack().getTopChild().getTopFullscreenAppToken(); @@ -214,7 +219,7 @@ public class RecentsAnimationController { private void addAnimation(Task task) { if (DEBUG) Log.d(TAG, "addAnimation(" + task.getName() + ")"); final SurfaceAnimator anim = new SurfaceAnimator(task, null /* animationFinishedCallback */, - mService.mAnimator::addAfterPrepareSurfacesRunnable, mService); + mService); final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task); anim.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */); task.commitPendingTransaction(); @@ -222,8 +227,10 @@ public class RecentsAnimationController { } void startAnimation() { - if (DEBUG) Log.d(TAG, "startAnimation(): mPendingStart=" + mPendingStart); - if (!mPendingStart) { + if (DEBUG) Log.d(TAG, "startAnimation(): mPendingStart=" + mPendingStart + + " mCanceled=" + mCanceled); + if (!mPendingStart || mCanceled) { + // Skip starting if we've already started or canceled the animation return; } try { diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java index c353c1d36d60..ae0f412a99bb 100644 --- a/services/core/java/com/android/server/wm/RemoteAnimationController.java +++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java @@ -96,13 +96,17 @@ class RemoteAnimationController { // Scale the timeout with the animator scale the controlling app is using. mHandler.postDelayed(mTimeoutRunnable, (long) (TIMEOUT_MS * mService.getCurrentAnimatorScale())); - try { - mRemoteAnimationAdapter.getRunner().onAnimationStart(createAnimations(), - mFinishedCallback); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to start remote animation", e); - onAnimationFinished(); - } + + final RemoteAnimationTarget[] animations = createAnimations(); + mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> { + try { + mRemoteAnimationAdapter.getRunner().onAnimationStart(animations, + mFinishedCallback); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to start remote animation", e); + onAnimationFinished(); + } + }); } private RemoteAnimationTarget[] createAnimations() { diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index f5760e593f37..2fe55b9ec117 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -588,6 +588,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); } + mService.mAnimator.executeAfterPrepareSurfacesRunnables(); + final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked; // If we are ready to perform an app transition, check through all of the app tokens to be @@ -798,7 +800,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { mService.enableScreenIfNeededLocked(); mService.scheduleAnimationLocked(); - mService.mWindowPlacerLocked.destroyPendingSurfaces(); if (DEBUG_WINDOW_TRACE) Slog.e(TAG, "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating()); diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index 83baee1ddbc6..37be1491c0aa 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -33,7 +33,6 @@ import android.view.SurfaceControl.Transaction; import com.android.internal.annotations.VisibleForTesting; import java.io.PrintWriter; -import java.util.function.Consumer; /** * A class that can run animations on objects that have a set of child surfaces. We do this by @@ -60,21 +59,17 @@ class SurfaceAnimator { /** * @param animatable The object to animate. * @param animationFinishedCallback Callback to invoke when an animation has finished running. - * @param addAfterPrepareSurfaces Consumer that takes a runnable and executes it after preparing - * surfaces in WM. Can be implemented differently during testing. */ SurfaceAnimator(Animatable animatable, @Nullable Runnable animationFinishedCallback, - Consumer<Runnable> addAfterPrepareSurfaces, WindowManagerService service) { + WindowManagerService service) { mAnimatable = animatable; mService = service; mAnimationFinishedCallback = animationFinishedCallback; - mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback, - addAfterPrepareSurfaces); + mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback); } private OnAnimationFinishedCallback getFinishedCallback( - @Nullable Runnable animationFinishedCallback, - Consumer<Runnable> addAfterPrepareSurfaces) { + @Nullable Runnable animationFinishedCallback) { return anim -> { synchronized (mService.mWindowMap) { final SurfaceAnimator target = mService.mAnimationTransferMap.remove(anim); @@ -83,30 +78,13 @@ class SurfaceAnimator { return; } - // TODO: This should use pendingTransaction eventually, but right now things - // happening on the animation finished callback are happening on the global - // transaction. - // For now we need to run this after it's guaranteed that the transaction that - // reparents the surface onto the leash is executed already. Otherwise this may be - // executed first, leading to surface loss, as the reparent operations wouldn't - // be in order. - addAfterPrepareSurfaces.accept(() -> { - if (anim != mAnimation) { - // Callback was from another animation - ignore. - return; - } - final Transaction t = new Transaction(); - SurfaceControl.openTransaction(); - try { - reset(t, true /* destroyLeash */); - if (animationFinishedCallback != null) { - animationFinishedCallback.run(); - } - } finally { - SurfaceControl.mergeToGlobalTransaction(t); - SurfaceControl.closeTransaction(); - } - }); + if (anim != mAnimation) { + return; + } + reset(mAnimatable.getPendingTransaction(), true /* destroyLeash */); + if (animationFinishedCallback != null) { + animationFinishedCallback.run(); + } } }; } @@ -290,7 +268,7 @@ class SurfaceAnimator { } mService.mAnimationTransferMap.remove(mAnimation); if (mLeash != null && destroyLeash) { - mAnimatable.destroyAfterPendingTransaction(mLeash); + t.destroy(mLeash); } mLeash = null; mAnimation = null; @@ -379,13 +357,6 @@ class SurfaceAnimator { void onAnimationLeashDestroyed(Transaction t); /** - * Destroy a given surface after executing {@link #getPendingTransaction}. - * - * @see WindowContainer#destroyAfterPendingTransaction - */ - void destroyAfterPendingTransaction(SurfaceControl surface); - - /** * @return A new surface to be used for the animation leash, inserted at the correct * position in the hierarchy. */ diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index a7a2b534131d..3d7b32ca1a9d 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -92,6 +92,7 @@ class TaskSnapshotController { private final TaskSnapshotPersister mPersister = new TaskSnapshotPersister( Environment::getDataSystemCeDirectory); private final TaskSnapshotLoader mLoader = new TaskSnapshotLoader(mPersister); + private final ArraySet<Task> mSkipClosingAppSnapshotTasks = new ArraySet<>(); private final ArraySet<Task> mTmpTasks = new ArraySet<>(); private final Handler mHandler = new Handler(); @@ -149,10 +150,20 @@ class TaskSnapshotController { // either closing or hidden. getClosingTasks(closingApps, mTmpTasks); snapshotTasks(mTmpTasks); + mSkipClosingAppSnapshotTasks.clear(); + } + /** + * Adds the given {@param tasks} to the list of tasks which should not have their snapshots + * taken upon the next processing of the set of closing apps. The caller is responsible for + * calling {@link #snapshotTasks} to ensure that the task has an up-to-date snapshot. + */ + @VisibleForTesting + void addSkipClosingAppSnapshotTasks(ArraySet<Task> tasks) { + mSkipClosingAppSnapshotTasks.addAll(tasks); } - private void snapshotTasks(ArraySet<Task> tasks) { + void snapshotTasks(ArraySet<Task> tasks) { for (int i = tasks.size() - 1; i >= 0; i--) { final Task task = tasks.valueAt(i); final int mode = getSnapshotMode(task); @@ -295,7 +306,7 @@ class TaskSnapshotController { // If the task of the app is not visible anymore, it means no other app in that task // is opening. Thus, the task is closing. - if (task != null && !task.isVisible()) { + if (task != null && !task.isVisible() && !mSkipClosingAppSnapshotTasks.contains(task)) { outClosingTasks.add(task); } } diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 49a30d5382c3..ab1019779b0b 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -92,6 +92,7 @@ public class WindowAnimator { * executed and the corresponding transaction is closed and applied. */ private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>(); + private boolean mInExecuteAfterPrepareSurfacesRunnables; WindowAnimator(final WindowManagerService service) { mService = service; @@ -225,13 +226,6 @@ public class WindowAnimator { if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION animate"); } - final int numDisplays = mDisplayContentsAnimators.size(); - for (int i = 0; i < numDisplays; i++) { - final int displayId = mDisplayContentsAnimators.keyAt(i); - final DisplayContent dc = mService.mRoot.getDisplayContent(displayId); - dc.onPendingTransactionApplied(); - } - boolean hasPendingLayoutChanges = mService.mRoot.hasPendingLayoutChanges(this); boolean doRequest = false; if (mBulkUpdateParams != 0) { @@ -265,7 +259,6 @@ public class WindowAnimator { } mService.destroyPreservedSurfaceLocked(); - mService.mWindowPlacerLocked.destroyPendingSurfaces(); executeAfterPrepareSurfacesRunnables(); @@ -434,11 +427,24 @@ public class WindowAnimator { * the corresponding transaction is closed and applied. */ void addAfterPrepareSurfacesRunnable(Runnable r) { + // If runnables are already being handled in executeAfterPrepareSurfacesRunnable, then just + // immediately execute the runnable passed in. + if (mInExecuteAfterPrepareSurfacesRunnables) { + r.run(); + return; + } + mAfterPrepareSurfacesRunnables.add(r); scheduleAnimation(); } - private void executeAfterPrepareSurfacesRunnables() { + void executeAfterPrepareSurfacesRunnables() { + + // Don't even think about to start recursing! + if (mInExecuteAfterPrepareSurfacesRunnables) { + return; + } + mInExecuteAfterPrepareSurfacesRunnables = true; // Traverse in order they were added. final int size = mAfterPrepareSurfacesRunnables.size(); @@ -446,5 +452,6 @@ public class WindowAnimator { mAfterPrepareSurfacesRunnables.get(i).run(); } mAfterPrepareSurfacesRunnables.clear(); + mInExecuteAfterPrepareSurfacesRunnables = false; } } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 6bd7f22a4a4c..fa4474ba3060 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -109,8 +109,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< WindowContainer(WindowManagerService service) { mService = service; mPendingTransaction = service.mTransactionFactory.make(); - mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, - service.mAnimator::addAfterPrepareSurfacesRunnable, service); + mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, service); } @Override @@ -286,8 +285,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } if (mSurfaceControl != null) { - destroyAfterPendingTransaction(mSurfaceControl); + getPendingTransaction().destroy(mSurfaceControl); mSurfaceControl = null; + scheduleAnimation(); } if (mParent != null) { @@ -1075,19 +1075,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< return mSurfaceControl; } - /** - * Destroy a given surface after executing mPendingTransaction. This is - * largely a workaround for destroy not being part of transactions - * rather than an intentional design, so please take care when - * expanding use. - */ - @Override - public void destroyAfterPendingTransaction(SurfaceControl surface) { - if (mParent != null) { - mParent.destroyAfterPendingTransaction(surface); - } - } - @Override public Transaction getPendingTransaction() { return mPendingTransaction; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c2ed2ae30227..966f6226caed 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2680,6 +2680,7 @@ public class WindowManagerService extends IWindowManager.Stub cancelRecentsAnimation(); mRecentsAnimationController = new RecentsAnimationController(this, recentsAnimationRunner, callbacks, displayId); + mRecentsAnimationController.initialize(); } } @@ -2687,6 +2688,19 @@ public class WindowManagerService extends IWindowManager.Stub return mRecentsAnimationController; } + /** + * @return Whether the next recents animation can continue to start. Called from + * {@link RecentsAnimation#startRecentsActivity}. + */ + public boolean canStartRecentsAnimation() { + synchronized (mWindowMap) { + if (mAppTransition.isTransitionSet()) { + return false; + } + return true; + } + } + public void cancelRecentsAnimation() { synchronized (mWindowMap) { if (mRecentsAnimationController != null) { @@ -2991,7 +3005,9 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void dismissKeyguard(IKeyguardDismissCallback callback, CharSequence message) { - checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard"); + if (!checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard")) { + throw new SecurityException("Requires CONTROL_KEYGUARD permission"); + } synchronized(mWindowMap) { mPolicy.dismissKeyguardLw(callback, message); } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 21b436112fda..c1a1452dae3d 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4067,7 +4067,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final boolean hasSurface = mWinAnimator.hasSurface(); if (hasSurface) { - mWinAnimator.hide("onExitAnimationDone"); + // Use pendingTransaction here so hide is done the same transaction as the other + // animations when exiting + mWinAnimator.hide(getPendingTransaction(), "onExitAnimationDone"); } // If we have an app token, we ask it to destroy the surface for us, so that it can take diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 9621ee527cac..a699ba00cd4e 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -164,6 +164,8 @@ class WindowStateAnimator { private boolean mAnimationStartDelayed; + private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction(); + /** The pixel format of the underlying SurfaceControl */ int mSurfaceFormat; @@ -280,16 +282,21 @@ class WindowStateAnimator { } } - void hide(String reason) { + void hide(SurfaceControl.Transaction transaction, String reason) { if (!mLastHidden) { //dump(); mLastHidden = true; if (mSurfaceController != null) { - mSurfaceController.hideInTransaction(reason); + mSurfaceController.hide(transaction, reason); } } } + void hide(String reason) { + hide(mTmpTransaction, reason); + SurfaceControl.mergeToGlobalTransaction(mTmpTransaction); + } + boolean finishDrawingLocked() { final boolean startingWindow = mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index 554a60023aff..d88e59c22aaa 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -86,6 +86,8 @@ class WindowSurfaceController { private final int mWindowType; private final Session mWindowSession; + private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction(); + public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format, int flags, WindowStateAnimator animator, int windowType, int ownerUid) { mAnimator = animator; @@ -148,21 +150,23 @@ class WindowSurfaceController { } } - void hideInTransaction(String reason) { + void hide(SurfaceControl.Transaction transaction, String reason) { if (SHOW_TRANSACTIONS) logSurface("HIDE ( " + reason + " )", null); mHiddenForOtherReasons = true; mAnimator.destroyPreservedSurfaceLocked(); - updateVisibility(); + if (mSurfaceShown) { + hideSurface(transaction); + } } - private void hideSurface() { + private void hideSurface(SurfaceControl.Transaction transaction) { if (mSurfaceControl == null) { return; } setShown(false); try { - mSurfaceControl.hide(); + transaction.hide(mSurfaceControl); } catch (RuntimeException e) { Slog.w(TAG, "Exception hiding surface in " + this); } @@ -421,7 +425,8 @@ class WindowSurfaceController { private boolean updateVisibility() { if (mHiddenForCrop || mHiddenForOtherReasons) { if (mSurfaceShown) { - hideSurface(); + hideSurface(mTmpTransaction); + SurfaceControl.mergeToGlobalTransaction(mTmpTransaction); } return false; } else { diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 7364e87227e4..272f3a5802c5 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -102,7 +102,6 @@ class WindowSurfacePlacer { } private final LayerAndToken mTmpLayerAndToken = new LayerAndToken(); - private final ArrayList<SurfaceControl> mPendingDestroyingSurfaces = new ArrayList<>(); private final SparseIntArray mTempTransitionReasons = new SparseIntArray(); private final Runnable mPerformSurfacePlacement; @@ -697,25 +696,6 @@ class WindowSurfacePlacer { } } - /** - * Puts the {@param surface} into a pending list to be destroyed after the current transaction - * has been committed. - */ - void destroyAfterTransaction(SurfaceControl surface) { - mPendingDestroyingSurfaces.add(surface); - } - - /** - * Destroys any surfaces that have been put into the pending list with - * {@link #destroyAfterTransaction}. - */ - void destroyPendingSurfaces() { - for (int i = mPendingDestroyingSurfaces.size() - 1; i >= 0; i--) { - mPendingDestroyingSurfaces.get(i).destroy(); - } - mPendingDestroyingSurfaces.clear(); - } - public void dump(PrintWriter pw, String prefix) { pw.println(prefix + "mTraversalScheduled=" + mTraversalScheduled); pw.println(prefix + "mHoldScreenWindow=" + mService.mRoot.mHoldScreenWindow); diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 72f95fb74f4f..0b032815f1fe 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -41,6 +41,7 @@ cc_library_static { "com_android_server_tv_TvUinputBridge.cpp", "com_android_server_tv_TvInputHal.cpp", "com_android_server_vr_VrManagerService.cpp", + "com_android_server_UsbAlsaJackDetector.cpp", "com_android_server_UsbDeviceManager.cpp", "com_android_server_UsbDescriptorParser.cpp", "com_android_server_UsbMidiDevice.cpp", @@ -97,6 +98,7 @@ cc_defaults { "libgui", "libusbhost", "libsuspend", + "libtinyalsa", "libEGL", "libGLESv2", "libnetutils", diff --git a/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp new file mode 100644 index 000000000000..e9d448234e17 --- /dev/null +++ b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp @@ -0,0 +1,152 @@ +/* + * 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. + */ + +#define LOG_TAG "UsbAlsaJackDetectorJNI" +#include "utils/Log.h" + +#include "jni.h" +#include <nativehelper/JNIHelp.h> +#include "android_runtime/AndroidRuntime.h" +#include "android_runtime/Log.h" + +#include <stdio.h> +#include <string.h> +#include <asm/byteorder.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <tinyalsa/asoundlib.h> + +#define DRIVER_NAME "/dev/usb_accessory" + +#define USB_IN_JACK_NAME "USB in Jack" +#define USB_OUT_JACK_NAME "USB out Jack" + +namespace android +{ + +static jboolean is_jack_connected(jint card, const char* control) { + struct mixer* card_mixer = mixer_open(card); + if (card_mixer == NULL) { + return true; + } + struct mixer_ctl* ctl = mixer_get_ctl_by_name(card_mixer, control); + if (!ctl) { + return true; + } + mixer_ctl_update(ctl); + int val = mixer_ctl_get_value(ctl, 0); + ALOGI("JACK %s - value %d\n", control, val); + mixer_close(card_mixer); + + return val != 0; +} + +static jboolean android_server_UsbAlsaJackDetector_hasJackDetect(JNIEnv* /* env */, + jobject /* thiz */, + jint card) +{ + struct mixer* card_mixer = mixer_open(card); + if (card_mixer == NULL) { + return false; + } + + jboolean has_jack = false; + if ((mixer_get_ctl_by_name(card_mixer, USB_IN_JACK_NAME) != NULL) || + (mixer_get_ctl_by_name(card_mixer, USB_OUT_JACK_NAME) != NULL)) { + has_jack = true; + } + mixer_close(card_mixer); + return has_jack; +} + + +static jboolean android_server_UsbAlsaJackDetector_inputJackConnected(JNIEnv* /* env */, + jobject /* thiz */, + jint card) +{ + return is_jack_connected(card, USB_IN_JACK_NAME); +} + + +static jboolean android_server_UsbAlsaJackDetector_outputJackConnected(JNIEnv* /* env */, + jobject /* thiz */, + jint card) +{ + return is_jack_connected(card, USB_OUT_JACK_NAME); +} + +static void android_server_UsbAlsaJackDetector_jackDetect(JNIEnv* env, + jobject thiz, + jint card) { + jclass jdclass = env->GetObjectClass(thiz); + jmethodID method_jackDetectCallback = env->GetMethodID(jdclass, "jackDetectCallback", "()Z"); + if (method_jackDetectCallback == NULL) { + ALOGE("Can't find jackDetectCallback"); + return; + } + + struct mixer* m = mixer_open(card); + if (!m) { + ALOGE("Jack detect unable to open mixer\n"); + return; + } + mixer_subscribe_events(m, 1); + do { + + // Wait for a mixer event. Retry if interrupted, exit on error. + int retval; + do { + retval = mixer_wait_event(m, -1); + } while (retval == -EINTR); + if (retval < 0) { + break; + } + mixer_consume_event(m); + } while (env->CallBooleanMethod(thiz, method_jackDetectCallback)); + + mixer_close(m); + return; +} + +static const JNINativeMethod method_table[] = { + { "nativeHasJackDetect", "(I)Z", (void*)android_server_UsbAlsaJackDetector_hasJackDetect }, + { "nativeInputJackConnected", "(I)Z", + (void*)android_server_UsbAlsaJackDetector_inputJackConnected }, + { "nativeOutputJackConnected", "(I)Z", + (void*)android_server_UsbAlsaJackDetector_outputJackConnected }, + { "nativeJackDetect", "(I)Z", (void*)android_server_UsbAlsaJackDetector_jackDetect }, +}; + +int register_android_server_UsbAlsaJackDetector(JNIEnv *env) +{ + jclass clazz = env->FindClass("com/android/server/usb/UsbAlsaJackDetector"); + if (clazz == NULL) { + ALOGE("Can't find com/android/server/usb/UsbAlsaJackDetector"); + return -1; + } + + if (!jniRegisterNativeMethods(env, "com/android/server/usb/UsbAlsaJackDetector", + method_table, NELEM(method_table))) { + ALOGE("Can't register UsbAlsaJackDetector native methods"); + return -1; + } + + return 0; +} + +} diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index bf2a637cf54e..0ebef37c1f2f 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -34,6 +34,7 @@ int register_android_server_PowerManagerService(JNIEnv* env); int register_android_server_storage_AppFuse(JNIEnv* env); int register_android_server_SerialService(JNIEnv* env); int register_android_server_SystemServer(JNIEnv* env); +int register_android_server_UsbAlsaJackDetector(JNIEnv* env); int register_android_server_UsbDeviceManager(JNIEnv* env); int register_android_server_UsbMidiDevice(JNIEnv* env); int register_android_server_UsbHostManager(JNIEnv* env); @@ -82,6 +83,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_AlarmManagerService(env); register_android_server_UsbDeviceManager(env); register_android_server_UsbMidiDevice(env); + register_android_server_UsbAlsaJackDetector(env); register_android_server_UsbHostManager(env); register_android_server_vr_VrManagerService(env); register_android_server_VibratorService(env); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java index 98c428dccf7a..091d9bd11a40 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java @@ -45,6 +45,7 @@ import java.nio.charset.StandardCharsets; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; /** * Unit tests for {@link android.app.admin.SystemUpdatePolicy}. @@ -253,6 +254,147 @@ public final class SystemUpdatePolicyTest { } + @Test + public void testInstallationOptionWithoutFreeze() { + // Also duplicated at com.google.android.gts.deviceowner.SystemUpdatePolicyTest + final long millis_2018_01_01 = TimeUnit.SECONDS.toMillis(1514764800); + + SystemUpdatePolicy p = SystemUpdatePolicy.createAutomaticInstallPolicy(); + assertInstallationOption(SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, Long.MAX_VALUE, + millis_2018_01_01, p); + + p = SystemUpdatePolicy.createPostponeInstallPolicy(); + assertInstallationOption(SystemUpdatePolicy.TYPE_POSTPONE, Long.MAX_VALUE, + millis_2018_01_01, p); + + p = SystemUpdatePolicy.createWindowedInstallPolicy(120, 180); // 2:00 - 3:00 + // 00:00 is two hours before the next window + assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(2), + millis_2018_01_01, p); + // 02:00 is within the current maintenance window, and one hour until the window ends + assertInstallationOption( + SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.HOURS.toMillis(1), + millis_2018_01_01 + TimeUnit.HOURS.toMillis(2), p); + // 04:00 is 22 hours from the window next day + assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(22), + millis_2018_01_01 + TimeUnit.HOURS.toMillis(4), p); + + p = SystemUpdatePolicy.createWindowedInstallPolicy(22 * 60, 2 * 60); // 22:00 - 2:00 + // 21:00 is one hour from the next window + assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(1), + millis_2018_01_01 + TimeUnit.HOURS.toMillis(21), p); + // 00:00 is two hours from the end of current window + assertInstallationOption( + SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.HOURS.toMillis(2), + millis_2018_01_01, p); + // 03:00 is 22 hours from the window today + assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(19), + millis_2018_01_01 + TimeUnit.HOURS.toMillis(3), p); + } + + @Test + public void testInstallationOptionWithFreeze() throws Exception { + final long millis_2016_02_29 = TimeUnit.SECONDS.toMillis(1456704000); + final long millis_2017_01_31 = TimeUnit.SECONDS.toMillis(1485820800); + final long millis_2017_02_28 = TimeUnit.SECONDS.toMillis(1488240000); + final long millis_2018_01_01 = TimeUnit.SECONDS.toMillis(1514764800); + final long millis_2018_08_01 = TimeUnit.SECONDS.toMillis(1533081600); + + SystemUpdatePolicy p = SystemUpdatePolicy.createAutomaticInstallPolicy(); + setFreezePeriods(p, "01-01", "01-31"); + // Inside a freeze period + assertInstallationOption( + SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(31), + millis_2018_01_01, p); + // Device is outside freeze between 2/28 to 12/31 inclusive + assertInstallationOption( + SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(307), + millis_2017_02_28, p); + + // Freeze period contains leap day Feb 29 + p = SystemUpdatePolicy.createPostponeInstallPolicy(); + setFreezePeriods(p, "02-01", "03-15"); + // Freezed until 3/31, note 2016 is a leap year + assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16), + millis_2016_02_29, p); + // Freezed until 3/31, note 2017 is not a leap year + assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16), + millis_2017_02_28, p); + // Next freeze is 2018/2/1 + assertInstallationOption(SystemUpdatePolicy.TYPE_POSTPONE, TimeUnit.DAYS.toMillis(31), + millis_2018_01_01, p); + + // Freeze period start on or right after leap day + p = SystemUpdatePolicy.createAutomaticInstallPolicy(); + setFreezePeriods(p, "03-01", "03-31"); + assertInstallationOption( + SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(1), + millis_2016_02_29, p); + assertInstallationOption( + SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(1), + millis_2017_02_28, p); + setFreezePeriods(p, "02-28", "03-15"); + assertInstallationOption( + SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16), + millis_2016_02_29, p); + assertInstallationOption( + SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16), + millis_2017_02_28, p); + + // Freeze period end on or right after leap day + p = SystemUpdatePolicy.createAutomaticInstallPolicy(); + setFreezePeriods(p, "02-01", "02-28"); + assertInstallationOption( + SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(1), + millis_2016_02_29, p); + assertInstallationOption( + SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(1), + millis_2017_02_28, p); + p = SystemUpdatePolicy.createAutomaticInstallPolicy(); + setFreezePeriods(p, "02-01", "03-01"); + assertInstallationOption( + SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(2), + millis_2016_02_29, p); + assertInstallationOption( + SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(2), + millis_2017_02_28, p); + + // Freeze period with maintenance window + p = SystemUpdatePolicy.createWindowedInstallPolicy(23 * 60, 1 * 60); // 23:00 - 1:00 + setFreezePeriods(p, "02-01", "02-28"); + // 00:00 is within the current window, outside freeze period + assertInstallationOption( + SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.HOURS.toMillis(1), + millis_2018_01_01, p); + // Last day of feeze period, which ends in 22 hours + assertInstallationOption( + SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(22), + millis_2017_02_28 + TimeUnit.HOURS.toMillis(2), p); + // Last day before the next freeze, and within window + assertInstallationOption( + SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.HOURS.toMillis(1), + millis_2017_01_31, p); + // Last day before the next freeze, and there is still a partial maintenance window before + // the freeze. + assertInstallationOption( + SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.HOURS.toMillis(19), + millis_2017_01_31 + TimeUnit.HOURS.toMillis(4), p); + + // Two freeze periods + p = SystemUpdatePolicy.createAutomaticInstallPolicy(); + setFreezePeriods(p, "05-01", "06-01", "12-01", "01-31"); + // automatic policy for August, September, November and December + assertInstallationOption( + SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(122), + millis_2018_08_01, p); + } + + private void assertInstallationOption(int expectedType, long expectedTime, long now, + SystemUpdatePolicy p) { + assertEquals(expectedType, p.getInstallationOptionAt(now).getType()); + assertEquals(expectedTime, p.getInstallationOptionAt(now).getEffectiveTime()); + } + private void testFreezePeriodsSucceeds(String...dates) throws Exception { SystemUpdatePolicy p = SystemUpdatePolicy.createPostponeInstallPolicy(); setFreezePeriods(p, dates); diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java index b55c79b4957d..79a9610bdbbd 100644 --- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java @@ -131,7 +131,6 @@ public class AppWindowContainerControllerTests extends WindowTestsBase { assertNoStartingWindow(controller.getAppWindowToken(mDisplayContent)); controller.getAppWindowToken(mDisplayContent).getParent().getParent().removeImmediately(); - mDisplayContent.onPendingTransactionApplied(); } } diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java index 64c303700639..a120eba623a3 100644 --- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java +++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java @@ -23,11 +23,11 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import android.platform.test.annotations.Presubmit; -import android.support.test.filters.FlakyTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.view.SurfaceControl; @@ -39,7 +39,6 @@ import com.android.server.wm.SurfaceAnimator.Animatable; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -47,7 +46,6 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; -import java.util.concurrent.CountDownLatch; /** * Test class for {@link SurfaceAnimatorTest}. @@ -87,7 +85,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { callbackCaptor.getValue().onAnimationFinished(mSpec); assertNotAnimating(mAnimatable); assertTrue(mAnimatable.mFinishedCallbackCalled); - assertTrue(mAnimatable.mPendingDestroySurfaces.contains(mAnimatable.mLeash)); + verify(mTransaction).destroy(eq(mAnimatable.mLeash)); // TODO: Verify reparenting once we use mPendingTransaction to reparent it back } @@ -97,7 +95,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { final SurfaceControl firstLeash = mAnimatable.mLeash; mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec2, true /* hidden */); - assertTrue(mAnimatable.mPendingDestroySurfaces.contains(firstLeash)); + verify(mTransaction).destroy(eq(firstLeash)); assertFalse(mAnimatable.mFinishedCallbackCalled); final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass( @@ -124,7 +122,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { assertNotAnimating(mAnimatable); verify(mSpec).onAnimationCancelled(any()); assertTrue(mAnimatable.mFinishedCallbackCalled); - assertTrue(mAnimatable.mPendingDestroySurfaces.contains(mAnimatable.mLeash)); + verify(mTransaction).destroy(eq(mAnimatable.mLeash)); } @Test @@ -145,7 +143,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { verifyZeroInteractions(mSpec); assertNotAnimating(mAnimatable); assertTrue(mAnimatable.mFinishedCallbackCalled); - assertTrue(mAnimatable.mPendingDestroySurfaces.contains(mAnimatable.mLeash)); + verify(mTransaction).destroy(eq(mAnimatable.mLeash)); } @Test @@ -161,11 +159,11 @@ public class SurfaceAnimatorTest extends WindowTestsBase { assertNotAnimating(mAnimatable); assertAnimating(mAnimatable2); assertEquals(leash, mAnimatable2.mSurfaceAnimator.mLeash); - assertFalse(mAnimatable.mPendingDestroySurfaces.contains(leash)); + verify(mTransaction, never()).destroy(eq(leash)); callbackCaptor.getValue().onAnimationFinished(mSpec); assertNotAnimating(mAnimatable2); assertTrue(mAnimatable2.mFinishedCallbackCalled); - assertTrue(mAnimatable2.mPendingDestroySurfaces.contains(leash)); + verify(mTransaction).destroy(eq(leash)); } private void assertAnimating(MyAnimatable animatable) { @@ -182,7 +180,6 @@ public class SurfaceAnimatorTest extends WindowTestsBase { final SurfaceControl mParent; final SurfaceControl mSurface; - final ArrayList<SurfaceControl> mPendingDestroySurfaces = new ArrayList<>(); final SurfaceAnimator mSurfaceAnimator; SurfaceControl mLeash; boolean mFinishedCallbackCalled; @@ -198,7 +195,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase { .build(); mFinishedCallbackCalled = false; mLeash = null; - mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, Runnable::run, sWm); + mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, sWm); } @Override @@ -219,11 +216,6 @@ public class SurfaceAnimatorTest extends WindowTestsBase { } @Override - public void destroyAfterPendingTransaction(SurfaceControl surface) { - mPendingDestroySurfaces.add(surface); - } - - @Override public Builder makeAnimationLeash() { return new SurfaceControl.Builder(mSession) { diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java index 920796ed6a30..5650050f0420 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java @@ -29,6 +29,7 @@ import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.util.ArraySet; +import com.google.android.collect.Sets; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,6 +75,21 @@ public class TaskSnapshotControllerTest extends WindowTestsBase { } @Test + public void testGetClosingApps_skipClosingAppsSnapshotTasks() throws Exception { + final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW, + "closingWindow"); + closingWindow.mAppToken.setVisibility(null, false /* visible */, TRANSIT_UNSET, + true /* performLayout */, false /* isVoiceInteraction */); + final ArraySet<AppWindowToken> closingApps = new ArraySet<>(); + closingApps.add(closingWindow.mAppToken); + final ArraySet<Task> closingTasks = new ArraySet<>(); + sWm.mTaskSnapshotController.addSkipClosingAppSnapshotTasks( + Sets.newArraySet(closingWindow.mAppToken.getTask())); + sWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks); + assertEquals(0, closingTasks.size()); + } + + @Test public void testGetSnapshotMode() throws Exception { final WindowState disabledWindow = createWindow(null, FIRST_APPLICATION_WINDOW, mDisplayContent, "disabledWindow"); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java index c532a8a25bda..6144c516750d 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -17,21 +17,32 @@ package com.android.server.notification; import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertEquals; import static junit.framework.TestCase.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.app.NotificationManager; +import android.content.ContentResolver; +import android.content.Context; +import android.content.res.Resources; import android.media.AudioAttributes; import android.provider.Settings; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.server.UiServiceTestCase; import org.junit.Before; @@ -46,15 +57,24 @@ import org.mockito.MockitoAnnotations; public class ZenModeHelperTest extends UiServiceTestCase { @Mock ConditionProviders mConditionProviders; + @Mock NotificationManager mNotificationManager; + @Mock private Resources mResources; private TestableLooper mTestableLooper; private ZenModeHelper mZenModeHelperSpy; + private Context mContext; + private ContentResolver mContentResolver; @Before public void setUp() { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); - mZenModeHelperSpy = spy(new ZenModeHelper(getContext(), mTestableLooper.getLooper(), + mContext = spy(getContext()); + mContentResolver = mContext.getContentResolver(); + when(mContext.getResources()).thenReturn(mResources); + when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager); + + mZenModeHelperSpy = spy(new ZenModeHelper(mContext, mTestableLooper.getLooper(), mConditionProviders)); } @@ -194,4 +214,31 @@ public class ZenModeHelperTest extends UiServiceTestCase { verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage); } } + + @Test + public void testZenUpgradeNotification() { + // shows zen upgrade notification if stored settings says to shows, boot is completed + // and we're setting zen mode on + Settings.Global.putInt(mContentResolver, Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1); + mZenModeHelperSpy.mIsBootComplete = true; + mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); + + verify(mZenModeHelperSpy, times(1)).createZenUpgradeNotification(); + verify(mNotificationManager, times(1)).notify(eq(ZenModeHelper.TAG), + eq(SystemMessage.NOTE_ZEN_UPGRADE), any()); + assertEquals(0, Settings.Global.getInt(mContentResolver, + Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, -1)); + } + + @Test + public void testNoZenUpgradeNotification() { + // doesn't show upgrade notification if stored settings says don't show + Settings.Global.putInt(mContentResolver, Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); + mZenModeHelperSpy.mIsBootComplete = true; + mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); + + verify(mZenModeHelperSpy, never()).createZenUpgradeNotification(); + verify(mNotificationManager, never()).notify(eq(ZenModeHelper.TAG), + eq(SystemMessage.NOTE_ZEN_UPGRADE), any()); + } } diff --git a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java index 7480e5662d7a..9d4db003a297 100644 --- a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java +++ b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java @@ -17,9 +17,14 @@ package com.android.server.usb; import android.annotation.NonNull; +import android.media.AudioSystem; +import android.media.IAudioService; +import android.os.RemoteException; import android.service.usb.UsbAlsaDeviceProto; +import android.util.Slog; import com.android.internal.util.dump.DualDumpOutputStream; +import com.android.server.audio.AudioService; /** * Represents the ALSA specification, and attributes of an ALSA device. @@ -30,25 +35,31 @@ public final class UsbAlsaDevice { private final int mCardNum; private final int mDeviceNum; - private final boolean mHasPlayback; - private final boolean mHasCapture; + private final String mDeviceAddress; + private final boolean mHasOutput; + private final boolean mHasInput; private final boolean mIsInputHeadset; private final boolean mIsOutputHeadset; - private final String mDeviceAddress; + private boolean mSelected = false; + private int mOutputState; + private int mInputState; + private UsbAlsaJackDetector mJackDetector; + private IAudioService mAudioService; private String mDeviceName = ""; private String mDeviceDescription = ""; - public UsbAlsaDevice(int card, int device, String deviceAddress, - boolean hasPlayback, boolean hasCapture, + public UsbAlsaDevice(IAudioService audioService, int card, int device, String deviceAddress, + boolean hasOutput, boolean hasInput, boolean isInputHeadset, boolean isOutputHeadset) { + mAudioService = audioService; mCardNum = card; mDeviceNum = device; mDeviceAddress = deviceAddress; - mHasPlayback = hasPlayback; - mHasCapture = hasCapture; + mHasOutput = hasOutput; + mHasInput = hasInput; mIsInputHeadset = isInputHeadset; mIsOutputHeadset = isOutputHeadset; } @@ -75,71 +86,187 @@ public final class UsbAlsaDevice { } /** - * @returns true if the device supports playback. + * @returns the ALSA card/device address string. */ - public boolean hasPlayback() { - return mHasPlayback; + public String getAlsaCardDeviceString() { + if (mCardNum < 0 || mDeviceNum < 0) { + Slog.e(TAG, "Invalid alsa card or device alsaCard: " + mCardNum + + " alsaDevice: " + mDeviceNum); + return null; + } + return AudioService.makeAlsaAddressString(mCardNum, mDeviceNum); } /** - * @returns true if the device supports capture (recording). + * @returns true if the device supports output. */ - public boolean hasCapture() { - return mHasCapture; + public boolean hasOutput() { + return mHasOutput; } /** - * @returns true if the device is a headset for purposes of capture. + * @returns true if the device supports input (recording). + */ + public boolean hasInput() { + return mHasInput; + } + + /** + * @returns true if the device is a headset for purposes of input. */ public boolean isInputHeadset() { return mIsInputHeadset; } /** - * @returns true if the device is a headset for purposes of playback. + * @returns true if the device is a headset for purposes of output. */ public boolean isOutputHeadset() { return mIsOutputHeadset; } /** + * @returns true if input jack is detected or jack detection is not supported. + */ + private synchronized boolean isInputJackConnected() { + if (mJackDetector == null) { + return true; // If jack detect isn't supported, say it's connected. + } + return mJackDetector.isInputJackConnected(); + } + + /** + * @returns true if input jack is detected or jack detection is not supported. + */ + private synchronized boolean isOutputJackConnected() { + if (mJackDetector == null) { + return true; // if jack detect isn't supported, say it's connected. + } + return mJackDetector.isOutputJackConnected(); + } + + /** Begins a jack-detection thread. */ + private synchronized void startJackDetect() { + // If no jack detect capabilities exist, mJackDetector will be null. + mJackDetector = UsbAlsaJackDetector.startJackDetect(this); + } + + /** Stops a jack-detection thread. */ + private synchronized void stopJackDetect() { + if (mJackDetector != null) { + mJackDetector.pleaseStop(); + } + mJackDetector = null; + } + + /** Start using this device as the selected USB Audio Device. */ + public synchronized void start() { + mSelected = true; + mInputState = 0; + mOutputState = 0; + startJackDetect(); + updateWiredDeviceConnectionState(true); + } + + /** Stop using this device as the selected USB Audio Device. */ + public synchronized void stop() { + stopJackDetect(); + updateWiredDeviceConnectionState(false); + mSelected = false; + } + + /** Updates AudioService with the connection state of the alsaDevice. + * Checks ALSA Jack state for inputs and outputs before reporting. + */ + public synchronized void updateWiredDeviceConnectionState(boolean enable) { + if (!mSelected) { + Slog.e(TAG, "updateWiredDeviceConnectionState on unselected AlsaDevice!"); + return; + } + String alsaCardDeviceString = getAlsaCardDeviceString(); + if (alsaCardDeviceString == null) { + return; + } + try { + // Output Device + if (mHasOutput) { + int device = mIsOutputHeadset + ? AudioSystem.DEVICE_OUT_USB_HEADSET + : AudioSystem.DEVICE_OUT_USB_DEVICE; + if (DEBUG) { + Slog.d(TAG, "pre-call device:0x" + Integer.toHexString(device) + + " addr:" + alsaCardDeviceString + + " name:" + mDeviceName); + } + boolean connected = isOutputJackConnected(); + Slog.i(TAG, "OUTPUT JACK connected: " + connected); + int outputState = (enable && connected) ? 1 : 0; + if (outputState != mOutputState) { + mOutputState = outputState; + mAudioService.setWiredDeviceConnectionState(device, outputState, + alsaCardDeviceString, + mDeviceName, TAG); + } + } + + // Input Device + if (mHasInput) { + int device = mIsInputHeadset ? AudioSystem.DEVICE_IN_USB_HEADSET + : AudioSystem.DEVICE_IN_USB_DEVICE; + boolean connected = isInputJackConnected(); + Slog.i(TAG, "INPUT JACK connected: " + connected); + int inputState = (enable && connected) ? 1 : 0; + if (inputState != mInputState) { + mInputState = inputState; + mAudioService.setWiredDeviceConnectionState( + device, inputState, alsaCardDeviceString, + mDeviceName, TAG); + } + } + } catch (RemoteException e) { + Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState"); + } + } + + + /** * @Override * @returns a string representation of the object. */ - public String toString() { + public synchronized String toString() { return "UsbAlsaDevice: [card: " + mCardNum + ", device: " + mDeviceNum + ", name: " + mDeviceName - + ", hasPlayback: " + mHasPlayback - + ", hasCapture: " + mHasCapture + "]"; + + ", hasOutput: " + mHasOutput + + ", hasInput: " + mHasInput + "]"; } /** * Write a description of the device to a dump stream. */ - public void dump(@NonNull DualDumpOutputStream dump, String idName, long id) { + public synchronized void dump(@NonNull DualDumpOutputStream dump, String idName, long id) { long token = dump.start(idName, id); dump.write("card", UsbAlsaDeviceProto.CARD, mCardNum); dump.write("device", UsbAlsaDeviceProto.DEVICE, mDeviceNum); dump.write("name", UsbAlsaDeviceProto.NAME, mDeviceName); - dump.write("has_playback", UsbAlsaDeviceProto.HAS_PLAYBACK, mHasPlayback); - dump.write("has_capture", UsbAlsaDeviceProto.HAS_CAPTURE, mHasCapture); + dump.write("has_output", UsbAlsaDeviceProto.HAS_PLAYBACK, mHasOutput); + dump.write("has_input", UsbAlsaDeviceProto.HAS_CAPTURE, mHasInput); dump.write("address", UsbAlsaDeviceProto.ADDRESS, mDeviceAddress); dump.end(token); } // called by logDevices - String toShortString() { + synchronized String toShortString() { return "[card:" + mCardNum + " device:" + mDeviceNum + " " + mDeviceName + "]"; } - String getDeviceName() { + synchronized String getDeviceName() { return mDeviceName; } - void setDeviceNameAndDescription(String deviceName, String deviceDescription) { + synchronized void setDeviceNameAndDescription(String deviceName, String deviceDescription) { mDeviceName = deviceName; mDeviceDescription = deviceDescription; } @@ -155,8 +282,8 @@ public final class UsbAlsaDevice { UsbAlsaDevice other = (UsbAlsaDevice) obj; return (mCardNum == other.mCardNum && mDeviceNum == other.mDeviceNum - && mHasPlayback == other.mHasPlayback - && mHasCapture == other.mHasCapture + && mHasOutput == other.mHasOutput + && mHasInput == other.mHasInput && mIsInputHeadset == other.mIsInputHeadset && mIsOutputHeadset == other.mIsOutputHeadset); } @@ -170,8 +297,8 @@ public final class UsbAlsaDevice { int result = 1; result = prime * result + mCardNum; result = prime * result + mDeviceNum; - result = prime * result + (mHasPlayback ? 0 : 1); - result = prime * result + (mHasCapture ? 0 : 1); + result = prime * result + (mHasOutput ? 0 : 1); + result = prime * result + (mHasInput ? 0 : 1); result = prime * result + (mIsInputHeadset ? 0 : 1); result = prime * result + (mIsOutputHeadset ? 0 : 1); diff --git a/services/usb/java/com/android/server/usb/UsbAlsaJackDetector.java b/services/usb/java/com/android/server/usb/UsbAlsaJackDetector.java new file mode 100644 index 000000000000..c4988478df71 --- /dev/null +++ b/services/usb/java/com/android/server/usb/UsbAlsaJackDetector.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.usb; + +/** + * Detects and reports ALSA jack state and events. + */ +public final class UsbAlsaJackDetector implements Runnable { + private static final String TAG = "UsbAlsaJackDetector"; + + private static native boolean nativeHasJackDetect(int card); + private native boolean nativeJackDetect(int card); + private native boolean nativeOutputJackConnected(int card); + private native boolean nativeInputJackConnected(int card); + + private boolean mStopJackDetect = false; + private UsbAlsaDevice mAlsaDevice; + + /* use startJackDetect to create a UsbAlsaJackDetector */ + private UsbAlsaJackDetector(UsbAlsaDevice device) { + mAlsaDevice = device; + } + + /** If jack detection is detected on the given Alsa Device, + * create and return a UsbAlsaJackDetector which will update wired device state + * each time a jack detection event is registered. + * + * @returns UsbAlsaJackDetector if jack detect is supported, or null. + */ + public static UsbAlsaJackDetector startJackDetect(UsbAlsaDevice device) { + if (!nativeHasJackDetect(device.getCardNum())) { + return null; + } + UsbAlsaJackDetector jackDetector = new UsbAlsaJackDetector(device); + + // This thread will exit once the USB device disappears. + // It can also be convinced to stop with pleaseStop(). + new Thread(jackDetector, "USB jack detect thread").start(); + return jackDetector; + } + + public boolean isInputJackConnected() { + return nativeInputJackConnected(mAlsaDevice.getCardNum()); + } + + public boolean isOutputJackConnected() { + return nativeOutputJackConnected(mAlsaDevice.getCardNum()); + } + + /** + * Stop the jack detect thread from calling back into UsbAlsaDevice. + * This doesn't force the thread to stop (which is deprecated in java and dangerous due to + * locking issues), but will cause the thread to exit at the next safe opportunity. + */ + public void pleaseStop() { + synchronized (this) { + mStopJackDetect = true; + } + } + + /** + * Called by nativeJackDetect each time a jack detect event is reported. + * @return false when the jackDetect thread should stop. true otherwise. + */ + public boolean jackDetectCallback() { + synchronized (this) { + if (mStopJackDetect) { + return false; + } + mAlsaDevice.updateWiredDeviceConnectionState(true); + } + return true; + } + + /** + * This will call jackDetectCallback each time it detects a jack detect event. + * If jackDetectCallback returns false, this function will return. + */ + public void run() { + nativeJackDetect(mAlsaDevice.getCardNum()); + } +} + diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java index 0c5f8f113adc..2f1c5169362a 100644 --- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java +++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java @@ -20,11 +20,9 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; import android.hardware.usb.UsbDevice; -import android.media.AudioSystem; import android.media.IAudioService; import android.media.midi.MidiDeviceInfo; import android.os.Bundle; -import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; import android.service.usb.UsbAlsaManagerProto; @@ -32,7 +30,6 @@ import android.util.Slog; import com.android.internal.alsa.AlsaCardsParser; import com.android.internal.util.dump.DualDumpOutputStream; -import com.android.server.audio.AudioService; import com.android.server.usb.descriptors.UsbDescriptorParser; import libcore.io.IoUtils; @@ -58,6 +55,7 @@ public final class UsbAlsaManager { // this is needed to map USB devices to ALSA Audio Devices, especially to remove an // ALSA device when we are notified that its associated USB device has been removed. private final ArrayList<UsbAlsaDevice> mAlsaDevices = new ArrayList<UsbAlsaDevice>(); + private UsbAlsaDevice mSelectedDevice; /** * List of connected MIDI devices @@ -78,17 +76,19 @@ public final class UsbAlsaManager { ServiceManager.getService(Context.AUDIO_SERVICE)); } - // Notifies AudioService when a device is added or removed - // audioDevice - the AudioDevice that was added or removed - // enabled - if true, we're connecting a device (it's arrived), else disconnecting - private void notifyDeviceState(UsbAlsaDevice alsaDevice, boolean enabled) { + /** + * Select the AlsaDevice to be used for AudioService. + * AlsaDevice.start() notifies AudioService of it's connected state. + * + * @param alsaDevice The selected UsbAlsaDevice for system USB audio. + */ + private synchronized void selectAlsaDevice(UsbAlsaDevice alsaDevice) { if (DEBUG) { - Slog.d(TAG, "notifyDeviceState " + enabled + " " + alsaDevice); + Slog.d(TAG, "selectAlsaDevice " + alsaDevice); } - if (mAudioService == null) { - Slog.e(TAG, "no AudioService"); - return; + if (mSelectedDevice != null) { + deselectAlsaDevice(); } // FIXME Does not yet handle the case where the setting is changed @@ -102,40 +102,14 @@ public final class UsbAlsaManager { return; } - int state = (enabled ? 1 : 0); - int cardNum = alsaDevice.getCardNum(); - int deviceNum = alsaDevice.getDeviceNum(); - if (cardNum < 0 || deviceNum < 0) { - Slog.e(TAG, "Invalid alsa card or device alsaCard: " + cardNum - + " alsaDevice: " + deviceNum); - return; - } - - String address = AudioService.makeAlsaAddressString(cardNum, deviceNum); - try { - // Playback Device - if (alsaDevice.hasPlayback()) { - int device = alsaDevice.isOutputHeadset() - ? AudioSystem.DEVICE_OUT_USB_HEADSET - : AudioSystem.DEVICE_OUT_USB_DEVICE; - if (DEBUG) { - Slog.i(TAG, "pre-call device:0x" + Integer.toHexString(device) + - " addr:" + address + " name:" + alsaDevice.getDeviceName()); - } - mAudioService.setWiredDeviceConnectionState( - device, state, address, alsaDevice.getDeviceName(), TAG); - } + mSelectedDevice = alsaDevice; + alsaDevice.start(); + } - // Capture Device - if (alsaDevice.hasCapture()) { - int device = alsaDevice.isInputHeadset() - ? AudioSystem.DEVICE_IN_USB_HEADSET - : AudioSystem.DEVICE_IN_USB_DEVICE; - mAudioService.setWiredDeviceConnectionState( - device, state, address, alsaDevice.getDeviceName(), TAG); - } - } catch (RemoteException e) { - Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState"); + private synchronized void deselectAlsaDevice() { + if (mSelectedDevice != null) { + mSelectedDevice.stop(); + mSelectedDevice = null; } } @@ -168,7 +142,7 @@ public final class UsbAlsaManager { Slog.d(TAG, " alsaDevice:" + alsaDevice); } if (alsaDevice != null) { - notifyDeviceState(alsaDevice, true /*enabled*/); + selectAlsaDevice(alsaDevice); } return alsaDevice; } else { @@ -202,16 +176,21 @@ public final class UsbAlsaManager { if (hasInput || hasOutput) { boolean isInputHeadset = parser.isInputHeadset(); boolean isOutputHeadset = parser.isOutputHeadset(); - UsbAlsaDevice alsaDevice = - new UsbAlsaDevice(cardRec.getCardNum(), 0 /*device*/, deviceAddress, - hasOutput, hasInput, isInputHeadset, isOutputHeadset); - alsaDevice.setDeviceNameAndDescription( - cardRec.getCardName(), cardRec.getCardDescription()); - mAlsaDevices.add(0, alsaDevice); - // Select it + if (mAudioService == null) { + Slog.e(TAG, "no AudioService"); + return; + } + + UsbAlsaDevice alsaDevice = + new UsbAlsaDevice(mAudioService, cardRec.getCardNum(), 0 /*device*/, + deviceAddress, hasOutput, hasInput, + isInputHeadset, isOutputHeadset); if (alsaDevice != null) { - notifyDeviceState(alsaDevice, true /*enabled*/); + alsaDevice.setDeviceNameAndDescription( + cardRec.getCardName(), cardRec.getCardDescription()); + mAlsaDevices.add(0, alsaDevice); + selectAlsaDevice(alsaDevice); } } @@ -256,7 +235,7 @@ public final class UsbAlsaManager { } } - /* package */ void usbDeviceRemoved(String deviceAddress/*UsbDevice usbDevice*/) { + /* package */ synchronized void usbDeviceRemoved(String deviceAddress/*UsbDevice usbDevice*/) { if (DEBUG) { Slog.d(TAG, "deviceRemoved(" + deviceAddress + ")"); } @@ -264,13 +243,9 @@ public final class UsbAlsaManager { // Audio UsbAlsaDevice alsaDevice = removeAlsaDeviceFromList(deviceAddress); Slog.i(TAG, "USB Audio Device Removed: " + alsaDevice); - if (alsaDevice != null) { - if (alsaDevice.hasPlayback() || alsaDevice.hasCapture()) { - notifyDeviceState(alsaDevice, false /*enabled*/); - - // if there any external devices left, select one of them - selectDefaultDevice(); - } + if (alsaDevice != null && alsaDevice == mSelectedDevice) { + deselectAlsaDevice(); + selectDefaultDevice(); // if there any external devices left, select one of them } // MIDI diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 680694732b2d..a7fc470864a5 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -1786,7 +1786,7 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver mGadgetProxy = IUsbGadget.getService(); mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(), USB_GADGET_HAL_DEATH_COOKIE); - if (!mCurrentFunctionsApplied) { + if (!mCurrentFunctionsApplied && !mCurrentUsbFunctionsRequested) { setEnabledFunctions(mCurrentFunctions, false); } } catch (NoSuchElementException e) { diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index 5fcff18aa5be..024bd303304f 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -29,7 +29,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; -import java.util.Objects; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; @@ -82,7 +81,7 @@ public abstract class Conference extends Conferenceable { private int mConnectionProperties; private String mDisconnectMessage; private long mConnectTimeMillis = CONNECT_TIME_NOT_SPECIFIED; - private long mConnectElapsedTimeMillis = CONNECT_TIME_NOT_SPECIFIED; + private long mConnectionStartElapsedRealTime = CONNECT_TIME_NOT_SPECIFIED; private StatusHints mStatusHints; private Bundle mExtras; private Set<String> mPreviousExtraKeys; @@ -584,30 +583,36 @@ public abstract class Conference extends Conferenceable { } /** - * Sets the connection start time of the {@code Conference}. Should be specified in wall-clock - * time returned by {@link System#currentTimeMillis()}. + * Sets the connection start time of the {@code Conference}. This is used in the call log to + * indicate the date and time when the conference took place. + * <p> + * Should be specified in wall-clock time returned by {@link System#currentTimeMillis()}. * <p> * When setting the connection time, you should always set the connection elapsed time via - * {@link #setConnectionElapsedTime(long)}. + * {@link #setConnectionStartElapsedRealTime(long)} to ensure the duration is reflected. * - * @param connectionTimeMillis The connection time, in milliseconds. + * @param connectionTimeMillis The connection time, in milliseconds, as returned by + * {@link System#currentTimeMillis()}. */ public final void setConnectionTime(long connectionTimeMillis) { mConnectTimeMillis = connectionTimeMillis; } /** - * Sets the elapsed time since system boot when the {@link Conference} was connected. - * This is used to determine the duration of the {@link Conference}. + * Sets the start time of the {@link Conference} which is the basis for the determining the + * duration of the {@link Conference}. + * <p> + * You should use a value returned by {@link SystemClock#elapsedRealtime()} to ensure that time + * zone changes do not impact the conference duration. * <p> - * When setting the connection elapsed time, you should always set the connection time via + * When setting this, you should also set the connection time via * {@link #setConnectionTime(long)}. * - * @param connectionElapsedTime The connection time, as measured by + * @param connectionStartElapsedRealTime The connection time, as measured by * {@link SystemClock#elapsedRealtime()}. */ - public final void setConnectionElapsedTime(long connectionElapsedTime) { - mConnectElapsedTimeMillis = connectionElapsedTime; + public final void setConnectionStartElapsedRealTime(long connectionStartElapsedRealTime) { + mConnectionStartElapsedRealTime = connectionStartElapsedRealTime; } /** @@ -642,8 +647,8 @@ public abstract class Conference extends Conferenceable { * @return The elapsed time at which the {@link Conference} was connected. * @hide */ - public final long getConnectElapsedTime() { - return mConnectElapsedTimeMillis; + public final long getConnectionStartElapsedRealTime() { + return mConnectionStartElapsedRealTime; } /** diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index d8599e8ca1fa..322970544281 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -2299,7 +2299,7 @@ public abstract class Connection extends Conferenceable { * * @hide */ - public final void setConnectElapsedTimeMillis(long connectElapsedTimeMillis) { + public final void setConnectionStartElapsedRealTime(long connectElapsedTimeMillis) { mConnectElapsedTimeMillis = connectElapsedTimeMillis; } diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 211699ea5940..1547857f23e3 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -21,7 +21,6 @@ import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -2007,7 +2006,7 @@ public abstract class ConnectionService extends Service { null : conference.getVideoProvider().getInterface(), conference.getVideoState(), conference.getConnectTimeMillis(), - conference.getConnectElapsedTime(), + conference.getConnectionStartElapsedRealTime(), conference.getStatusHints(), conference.getExtras()); diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp index e301eb140fc9..dc2ed433d345 100644 --- a/tools/stats_log_api_gen/Android.bp +++ b/tools/stats_log_api_gen/Android.bp @@ -102,6 +102,7 @@ cc_library_shared { export_generated_headers: ["statslog.h"], shared_libs: [ "liblog", + "libutils", ], } diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp index 3dbb50306cc6..a78b1a2b0731 100644 --- a/tools/stats_log_api_gen/main.cpp +++ b/tools/stats_log_api_gen/main.cpp @@ -105,6 +105,7 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, fprintf(out, "#include <log/log_event_list.h>\n"); fprintf(out, "#include <log/log.h>\n"); fprintf(out, "#include <statslog.h>\n"); + fprintf(out, "#include <utils/SystemClock.h>\n"); fprintf(out, "\n"); fprintf(out, "namespace android {\n"); @@ -145,6 +146,7 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, fprintf(out, "{\n"); argIndex = 1; fprintf(out, " android_log_event_list event(kStatsEventTag);\n"); + fprintf(out, " event << android::elapsedRealtimeNano();\n\n"); fprintf(out, " event << code;\n\n"); for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { |