Merge "Updates statsd atoms.proto with small changes."
diff --git a/Android.bp b/Android.bp
index 05fb3c0..e65ba0f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -249,8 +249,7 @@
"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 @@
"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 @@
"system/netd/server/binder",
"system/vold/binder",
"system/bt/binder",
+ "system/security/keystore/binder",
],
},
diff --git a/Android.mk b/Android.mk
index f420820..3b8d6a8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -804,7 +804,7 @@
-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 3edd2c0..042360e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3695,7 +3695,7 @@
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 @@
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 @@
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 @@
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 953941f..39cbe90 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -437,6 +437,19 @@
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 @@
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 @@
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 3a20b12..afb2c47 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 @@
// 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::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 @@
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 @@
// 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 @@
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 @@
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 @@
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 7ca125a..18ada65 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 @@
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 @@
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 06ff603..fbb0fdd 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -101,7 +101,7 @@
}
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 d0d2f93..d1d9d37 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 @@
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 @@
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 d9aeb46..568b8f0 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 @@
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 @@
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 0e126e7..0b545cc 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 @@
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 @@
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 7684ed4..cc80204 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 @@
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 @@
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 72fb5ff..261cb43 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 @@
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 @@
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 8210c8d..bd859fd 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 @@
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 fc0ad7c..9513cc5 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 @@
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 4c676a7..08c59cf 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 @@
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::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 65a1df0e..4501b64 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 @@
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 @@
(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 @@
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 @@
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 06c5b00..e2e9426 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -80,7 +80,7 @@
// 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::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::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::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::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::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::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 @@
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::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 @@
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 ce3a4b9..7489d9b 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -33,7 +33,7 @@
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(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 @@
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 @@
} break;
case EVENT_TYPE_LONG: {
- if (depth < 0 || depth > 2) {
- ALOGE("Depth > 2. Not supported!");
- return;
+ 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]++;
}
- 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 @@
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 @@
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 0895daa..b3084d5 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -47,14 +47,18 @@
/**
* 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 @@
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 @@
// 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 bd2674b..178db1a 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_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 @@
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 @@
}
// 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 @@
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 6b321e1..af22578c 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_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 @@
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 @@
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 @@
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 ed7e44d..2585aa3 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 @@
// 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 @@
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 da0cafe..af3b4c5 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_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 @@
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 @@
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 @@
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 beb9015..f3307dc 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -25,7 +25,7 @@
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 53cb193..66e1aeb 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 @@
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 @@
protoOutput->end(token);
}
}
- mLastReportTimeNs = ::android::elapsedRealtimeNano();
+ mLastReportTimeNs = dumpTimeStampNs;
VLOG("=========================Metric Reports End==========================");
}
@@ -230,7 +232,7 @@
}
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 45b4ac0..cbca884 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -219,19 +219,19 @@
}
// 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 @@
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 6701a46..b518f2f 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -62,7 +62,7 @@
// 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 @@
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 691423e..e322ca4 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 @@
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 @@
}
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::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 @@
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::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 @@
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 @@
}
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 @@
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 @@
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 @@
// 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 b56cffb..b427485 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -42,15 +42,17 @@
}
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 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 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 @@
repeated Atom atom = 3;
- repeated int64 timestamp_nanos = 4;
+ repeated int64 elapsed_timestamp_nanos = 4;
}
message GaugeMetricData {
@@ -122,7 +124,7 @@
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 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 @@
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 86c258b..e735770 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 @@
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 6583f57..32fe0b8 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -35,6 +35,24 @@
// 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 23bd5561..6a1db72 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 @@
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 01743ef..93cd587 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -163,11 +163,11 @@
"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 @@
"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 @@
"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 @@
"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 275b5824..293f579 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_test.cpp
@@ -142,8 +142,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 3b25694b..024fa3e 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -315,9 +315,9 @@
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 a134300..bd11443 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -225,7 +225,7 @@
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 1e71b73..d9dbf1d 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -48,7 +48,9 @@
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 @@
// 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 @@
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 @@
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 @@
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 23e15f7..57e2794 100644
--- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
@@ -51,7 +51,9 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 26f7c26..8b4273b 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -387,7 +387,7 @@
.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 @@
.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 293b1a8..cb731c5 100644
--- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
@@ -59,7 +59,6 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 325a372..6e66c6e 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -406,16 +406,16 @@
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 d3a89617..b7acef7 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -406,7 +406,7 @@
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 03e5fef..b6b16e4 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 @@
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 @@
}
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 @@
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 @@
}
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 87b82c2..d55f3f3 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 @@
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 @@
}
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 @@
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 @@
}
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 f7c5c57..fb27f74 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -7,33 +7,3 @@
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 0bc510a..bcd88fe 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1733,7 +1733,7 @@
*
* <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 @@
}
/**
- * 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 @@
* @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 5a63319..a69b0ee 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3904,62 +3904,6 @@
}
}
- 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 7acdfc8..de5e21a 100644
--- a/core/java/android/app/admin/FreezeInterval.java
+++ b/core/java/android/app/admin/FreezeInterval.java
@@ -84,6 +84,10 @@
}
}
+ 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 @@
* 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 202b894..69ec26c 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -78,6 +78,8 @@
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 @@
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 @@
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 b64b7e3..fe2519d 100644
--- a/core/java/android/app/admin/SecurityLogTags.logtags
+++ b/core/java/android/app/admin/SecurityLogTags.logtags
@@ -35,4 +35,6 @@
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 05d3fd9..47b3a81 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.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 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 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 @@
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 @@
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 @@
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 @@
}
}
+ @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 aa8faf8..07a9911 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2070,6 +2070,15 @@
"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 fef6495..1223271 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11391,6 +11391,14 @@
"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 @@
* @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 96a1a04..0000000
--- 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 738eb68..0000000
--- 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 dc8ed50..0000000
--- 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 1748653..0000000
--- 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 32e75ad..0000000
--- 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/KeymasterArguments.aidl b/core/java/android/security/keymaster/KeymasterArguments.aidl
deleted file mode 100644
index 44d9f09..0000000
--- a/core/java/android/security/keymaster/KeymasterArguments.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 KeymasterArguments cpp_header "keystore/KeymasterArguments.h";
diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.aidl b/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
deleted file mode 100644
index ddb5cae..0000000
--- 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 db689d4..0000000
--- 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 d66322c..171d4d9 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -94,7 +94,7 @@
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 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 @@
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 bd7f8e5..fc78211 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -152,6 +152,7 @@
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 @@
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 bb9e391..7bae28a 100644
--- a/core/java/android/view/WindowInfo.java
+++ b/core/java/android/view/WindowInfo.java
@@ -21,6 +21,7 @@
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 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 @@
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 @@
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 1c5e871..c0a9666 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -63,6 +63,7 @@
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 @@
*
* @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 @@
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 @@
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 4a181b2..44adbb2 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -49,6 +49,7 @@
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 @@
.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 eb58b09..6a56f45 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -187,7 +187,7 @@
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 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 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 @@
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 @@
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 @@
@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 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 @@
*/
void reset(boolean detachIfReset) {
mCount = 0;
- mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
+ mLoadedCount = mUnpluggedCount = 0;
if (detachIfReset) {
detach();
}
@@ -1531,7 +1536,7 @@
void readSummaryFromParcelLocked(Parcel in) {
mLoadedCount = in.readLong();
mCount = mLoadedCount;
- mUnpluggedCount = mPluggedCount = mLoadedCount;
+ mUnpluggedCount = mLoadedCount;
}
}
@@ -3852,9 +3857,6 @@
+ 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 @@
}
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 boolean startAddingCpuLocked() {
- mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
+ mExternalSync.cancelCpuSyncDueToWakelockChange();
return mOnBatteryInternal;
}
@@ -4807,6 +4805,8 @@
+ 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 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 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 @@
// 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 @@
// 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 @@
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 @@
* @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 @@
}
cpuSpeeds[speed].addCountLocked(appCpuTimeUs
* clusterSpeedTimesMs[cluster][speed]
- / totalCpuClustersTimeMs);
+ / totalCpuClustersTimeMs, onBattery);
}
}
}
@@ -11926,7 +11943,7 @@
*/
@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 @@
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 @@
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 @@
* @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 @@
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 @@
} else {
appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
}
- cpuTimesUs[speed].addCountLocked(appAllocationUs);
+ cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
freqIndex++;
}
}
@@ -12132,7 +12150,7 @@
}
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 @@
* 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 @@
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 @@
* 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 @@
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 @@
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 @@
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 65615c0..444049e 100644
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
@@ -78,10 +78,11 @@
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 @@
}
}
- 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 e69a360..fac6b23 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -53,8 +53,8 @@
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 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 74802c8..9c89976 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -98,10 +98,6 @@
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 @@
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 0ef5445..8ca5062 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -846,6 +846,14 @@
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 @@
(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 f2b7ab2..02fc4da 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -399,6 +399,7 @@
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 @@
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 fc75f04..c70b122 100644
--- a/core/res/res/drawable/ic_settings_24dp.xml
+++ b/core/res/res/drawable/ic_settings_24dp.xml
@@ -16,9 +16,9 @@
<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 cf7925b..0218750 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 ec81df7..0efb6f9 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 af25398..5a9dc7f 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 a446088..7849a2a 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 a0b6297..dc8ed9e 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -354,6 +354,7 @@
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 @@
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 32053e3..cb049b7 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 @@
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 @@
mBatteryStatsImpl.setOnBatteryInternal(true);
// RUN
- mBatteryStatsImpl.updateCpuTimeLocked();
+ mBatteryStatsImpl.updateCpuTimeLocked(true, false);
// VERIFY
verify(mUserInfoProvider).refreshUserIds();
@@ -213,7 +213,7 @@
}
// RUN
- mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids);
+ mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids, true);
// VERIFY
int totalClustersTimeMs = 0;
@@ -261,7 +261,7 @@
// 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 @@
}).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 @@
}).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 @@
}).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 @@
}).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 @@
// RUN
final SparseLongArray updatedUids = new SparseLongArray();
- mBatteryStatsImpl.readKernelUidCpuTimesLocked(partialTimers, updatedUids);
+ mBatteryStatsImpl.readKernelUidCpuTimesLocked(partialTimers, updatedUids, true);
// VERIFY
long totalUserTimeUs = 0;
@@ -549,7 +549,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
any(KernelUidCpuActiveTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked();
+ mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -1073,7 +1073,7 @@
any(KernelUidCpuActiveTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked();
+ mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -1112,7 +1112,7 @@
any(KernelUidCpuClusterTimeReader.Callback.class));
// RUN
- mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked();
+ mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true);
// VERIFY
for (int i = 0; i < testUids.length; ++i) {
@@ -1142,7 +1142,7 @@
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 82ac9da..01ddc15 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 @@
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 @@
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 7b239f0..cb05253 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 @@
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 0be54ec..9ff964b 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.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 @@
}
}
+
+ /**
+ * @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/KeymasterBlob.aidl b/media/java/android/media/IAudioServerStateDispatcher.aidl
similarity index 67%
rename from core/java/android/security/keymaster/KeymasterBlob.aidl
rename to media/java/android/media/IAudioServerStateDispatcher.aidl
index 5c5db9e..2bc90ea 100644
--- a/core/java/android/security/keymaster/KeymasterBlob.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 KeymasterBlob cpp_header "keystore/KeymasterBlob.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 4c37014..05ba4c3 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -24,10 +24,12 @@
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 @@
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 b8184a0..b8d01c4 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -119,7 +119,8 @@
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 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 @@
callback.mSession = this;
CallbackMessageHandler msgHandler = new CallbackMessageHandler(handler.getLooper(),
callback);
- mCallbackHandler = msgHandler;
+ mCallback = msgHandler;
}
}
@@ -634,8 +635,8 @@
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 1551b8e..769b7e9 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 @@
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 @@
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 faa2c17..31635a5 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
new file mode 100644
index 0000000..2d62a80
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step.png
Binary files differ
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
new file mode 100644
index 0000000..a52e5b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
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
new file mode 100644
index 0000000..d13c730
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step.png
Binary files differ
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
new file mode 100644
index 0000000..31c602e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step_dark.png
Binary files differ
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
new file mode 100644
index 0000000..ddbcb07
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step.png
Binary files differ
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
new file mode 100644
index 0000000..ce91fcbb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step_dark.png
Binary files differ
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
new file mode 100644
index 0000000..c606a58
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step.png
Binary files differ
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
new file mode 100644
index 0000000..c2a5fef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step_dark.png
Binary files differ
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 0000000..b517fc8
--- /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 0000000..eafd663
--- /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 8078c41..2470947 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 4fcfdf7..be8e990 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 3f6c85f..a62f38b 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 dc082a9..8c59e75 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 7f382ac..e200a7f 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 @@
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 62bd72f..138910c 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 @@
}
/**
+ * 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 0000000..f622d4a
--- /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 e440731..3b5f34c 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 @@
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 @@
if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
refresh();
updateOwnerInfo();
+ updateLogoutView();
}
}
@@ -97,6 +103,12 @@
public void onUserSwitchComplete(int userId) {
refresh();
updateOwnerInfo();
+ updateLogoutView();
+ }
+
+ @Override
+ public void onLogoutEnabledChanged() {
+ updateLogoutView();
}
};
@@ -111,6 +123,7 @@
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 @@
@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 @@
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 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 @@
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 @@
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 9e4b405..f3f8d91f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -141,6 +141,7 @@
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 @@
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 @@
case MSG_FINGERPRINT_AUTHENTICATION_CONTINUE:
updateFingerprintListeningState();
break;
+ case MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED:
+ updateLogoutEnabled();
+ break;
}
}
};
@@ -795,6 +801,9 @@
}
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 @@
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 @@
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
mUserManager = context.getSystemService(UserManager.class);
+ mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
+ mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
}
private void updateFingerprintListeningState() {
@@ -1936,6 +1948,26 @@
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 1afcca6..67571bb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -283,4 +283,11 @@
* @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 c28b7ee..259bff2 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 @@
}
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 @@
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 @@
}
@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 eb5619b..0876507 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 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 b3f68d3..2723df7 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 @@
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 @@
showBlockingHelper(mEntry.userSentiment ==
NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+ updateRippleAllowed();
}
@VisibleForTesting
@@ -1805,6 +1798,13 @@
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 ab89a52..0ff4dde 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.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 @@
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 @@
@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 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 @@
}
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 1239a9e..72938c2 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 @@
/** 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 @@
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 @@
// 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 @@
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 @@
if (shouldOverrideUserLockPrefs(rotation)) {
mRotationLockController.setRotationLockedAtAngle(true, rotation);
}
- setRotateSuggestionButtonState(false, true);
+ safeSetRotationButtonState(false, true);
}
if (mNavigationBarView != null
@@ -928,22 +858,22 @@
@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 @@
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 d15c771..63f2ceb 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 @@
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 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 9d20e4e..9894235 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 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 @@
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 @@
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 af0afbd..53dc814 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.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 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.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 @@
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 @@
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 @@
private RecentsOnboarding mRecentsOnboarding;
private NotificationPanelView mPanelView;
+ private Animator mRotateHideAnimator;
+
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
private boolean mHomeAppearing;
@@ -217,6 +237,9 @@
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 @@
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 @@
@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 @@
return super.onTouchEvent(event);
}
+ public @NavigationBarCompat.HitTarget int getDownHitTarget() {
+ return mDownHitTarget;
+ }
+
public void abortCurrentGesture() {
getHomeButton().abortCurrentGesture();
}
@@ -355,14 +391,23 @@
}
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 @@
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 @@
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 @@
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 @@
setSlippery(!isConnected);
setDisabledFlags(mDisabledFlags, true);
setUpSwipeUpOnboarding(isConnected);
+ updateIcons(getContext(), Configuration.EMPTY, mConfiguration);
+ setNavigationIconHints(mNavigationIconHints, true);
}
@Override
@@ -677,9 +810,23 @@
@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 0e8fcba..3b129fc 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 @@
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 dc0835e..bb2f597 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_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 @@
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 @@
@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 @@
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 @@
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 @@
}
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 1438763..94ebc1b 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 @@
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 @@
private boolean mScreenBlankingCallbackCalled;
private Callback mCallback;
private boolean mWallpaperSupportsAmbientMode;
+ private boolean mScreenOn;
// Scrim blanking callbacks
private Choreographer.FrameCallback mPendingFrameCallback;
@@ -251,6 +253,7 @@
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 @@
* @param fraction From 0 to 1 where 0 means collapse and 1 expanded.
*/
public void setPanelExpansion(float fraction) {
- if (mFraction != fraction) {
- mFraction = fraction;
+ if (mExpansionFraction != fraction) {
+ mExpansionFraction = 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 (!(mState == ScrimState.UNLOCKED || mState == ScrimState.KEYGUARD)) {
+ return;
+ }
- // 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 {
+ 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 @@
}
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 @@
// 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 @@
} 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 @@
* 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 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 458518c..3b63d6c 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 @@
@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 c30f633..948f524 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 @@
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 1da50ad..503a1b4 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 @@
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 @@
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 9d1c1e8..98bebec 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.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 @@
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 45abd45..eb0c89b 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_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 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 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 @@
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 43e16db..4702793 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 @@
@Test
public void transitionToUnlocked() {
+ mScrimController.setPanelExpansion(0f);
mScrimController.transitionTo(ScrimState.UNLOCKED);
mScrimController.finishAnimationsImmediately();
// Front scrim should be transparent
@@ -197,6 +198,7 @@
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 @@
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 08fdb97..608970f 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -204,6 +204,10 @@
// 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 @@
// 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 6747be3..5e5eacb 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.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 @@
IBinder binder;
+ TelephonyRegistryDeathRecipient deathRecipient;
+
IPhoneStateListener callback;
IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
@@ -251,6 +254,21 @@
}
};
+ 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 @@
}
}
- 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 @@
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 @@
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 14404f5..5fc4373 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 @@
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 @@
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 @@
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 c958b67..e8b7839 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.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.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 @@
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 @@
}
}
+ /**
+ * 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 @@
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 @@
}
};
+ mHiddenApiBlacklist = new HiddenApiBlacklist(mHandler, mContext);
+
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
@@ -4090,10 +4130,10 @@
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 @@
"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 @@
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 @@
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 ef82f36..fba0377 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.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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
};
@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 @@
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 ea52782..9d1adb2 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 @@
// 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 db4e09f..6dcf041 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.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 @@
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 @@
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 @@
.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 @@
// 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 @@
});
}
}
+
+ /**
+ * 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 e95608f..fffe7dc 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.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 @@
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 @@
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 @@
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 @@
onAudioServerDied();
break;
+ case MSG_DISPATCH_AUDIO_SERVER_STATE:
+ onDispatchAudioServerStateChange(msg.arg1 == 1);
+ break;
+
case MSG_UNLOAD_SOUND_EFFECTS:
onUnloadSoundEffects();
break;
@@ -7341,6 +7364,77 @@
//======================
+ // 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 b877184..21d86c4 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.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.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 @@
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 @@
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 @@
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 @@
} 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 @@
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 7e3b551..0a87097 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 @@
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.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 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 @@
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 @@
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 @@
mHandler.postMetricsTimer();
cleanUpZenRules();
evaluateZenMode("onSystemReady", true);
+ mIsBootComplete = true;
+ showZenUpgradeNotification(mZenMode);
}
public void onUserSwitched(int user) {
@@ -612,6 +622,10 @@
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 @@
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 @@
}
}
+ 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 b79caca..1746dd1 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 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 2c68e67..458d725 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_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 @@
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 @@
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 0502848..d9bcc5c 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 @@
// 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 4bc9404..9f9b1af 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 @@
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 @@
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 db95634..3cd3e8b 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 @@
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 @@
}
@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 4394a99..a180a3a 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 @@
}
@Override
- public void destroyAfterPendingTransaction(SurfaceControl surface) {
- mHost.destroyAfterPendingTransaction(surface);
- }
-
- @Override
public SurfaceControl.Builder makeAnimationLeash() {
return mHost.makeAnimationLeash();
}
@@ -119,7 +114,7 @@
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 41a6e2b..f421bf4 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 @@
*/
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 @@
}
}
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 @@
}
@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 @@
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 e869f58..e4edeb87 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.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.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 @@
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 @@
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 @@
};
/**
- * 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 @@
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 @@
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 @@
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 @@
}
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 c353c1d..ae0f412 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 @@
// 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 f5760e5..2fe55b9 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 @@
"<<< 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 @@
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 83baee1..37be149 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 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 @@
/**
* @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 @@
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 @@
}
mService.mAnimationTransferMap.remove(mAnimation);
if (mLeash != null && destroyLeash) {
- mAnimatable.destroyAfterPendingTransaction(mLeash);
+ t.destroy(mLeash);
}
mLeash = null;
mAnimation = null;
@@ -379,13 +357,6 @@
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 a7a2b53..3d7b32c 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 @@
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 @@
// either closing or hidden.
getClosingTasks(closingApps, mTmpTasks);
snapshotTasks(mTmpTasks);
-
+ mSkipClosingAppSnapshotTasks.clear();
}
- private void snapshotTasks(ArraySet<Task> tasks) {
+ /**
+ * 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);
+ }
+
+ 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 @@
// 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 49a30d5..ab10197 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 @@
* 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 @@
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 @@
}
mService.destroyPreservedSurfaceLocked();
- mService.mWindowPlacerLocked.destroyPendingSurfaces();
executeAfterPrepareSurfacesRunnables();
@@ -434,11 +427,24 @@
* 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 @@
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 6bd7f22..fa4474b 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 @@
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 @@
}
if (mSurfaceControl != null) {
- destroyAfterPendingTransaction(mSurfaceControl);
+ getPendingTransaction().destroy(mSurfaceControl);
mSurfaceControl = null;
+ scheduleAnimation();
}
if (mParent != null) {
@@ -1075,19 +1075,6 @@
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 c2ed2ae..966f622 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 @@
cancelRecentsAnimation();
mRecentsAnimationController = new RecentsAnimationController(this,
recentsAnimationRunner, callbacks, displayId);
+ mRecentsAnimationController.initialize();
}
}
@@ -2687,6 +2688,19 @@
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 @@
@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 21b4361..c1a1452 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 @@
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 9621ee5..a699ba0 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 @@
private boolean mAnimationStartDelayed;
+ private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
+
/** The pixel format of the underlying SurfaceControl */
int mSurfaceFormat;
@@ -280,16 +282,21 @@
}
}
- 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 554a600..d88e59c 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 @@
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 @@
}
}
- 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 @@
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 7364e87..272f3a5 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 @@
}
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 @@
}
}
- /**
- * 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 72f95fb..0b03281 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -41,6 +41,7 @@
"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 @@
"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 0000000..e9d4482
--- /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 bf2a637..0ebef37 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -34,6 +34,7 @@
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 @@
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 98c428d..091d9bd 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.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 @@
}
+ @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 b55c79b..79a9610 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 @@
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 64c3037..a120eba 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.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.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.MockitoAnnotations;
import java.util.ArrayList;
-import java.util.concurrent.CountDownLatch;
/**
* Test class for {@link SurfaceAnimatorTest}.
@@ -87,7 +85,7 @@
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 @@
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 @@
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 @@
verifyZeroInteractions(mSpec);
assertNotAnimating(mAnimatable);
assertTrue(mAnimatable.mFinishedCallbackCalled);
- assertTrue(mAnimatable.mPendingDestroySurfaces.contains(mAnimatable.mLeash));
+ verify(mTransaction).destroy(eq(mAnimatable.mLeash));
}
@Test
@@ -161,11 +159,11 @@
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 @@
final SurfaceControl mParent;
final SurfaceControl mSurface;
- final ArrayList<SurfaceControl> mPendingDestroySurfaces = new ArrayList<>();
final SurfaceAnimator mSurfaceAnimator;
SurfaceControl mLeash;
boolean mFinishedCallbackCalled;
@@ -198,7 +195,7 @@
.build();
mFinishedCallbackCalled = false;
mLeash = null;
- mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, Runnable::run, sWm);
+ mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, sWm);
}
@Override
@@ -219,11 +216,6 @@
}
@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 920796e..5650050 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.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 @@
}
@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 c532a8a..6144c51 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 @@
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 @@
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 7480e56..9d4db00 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 @@
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 @@
}
/**
- * @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 @@
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 @@
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 0000000..c498847
--- /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 0c5f8f1..2f1c516 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.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 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 @@
// 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 @@
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 @@
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;
- }
+ mSelectedDevice = alsaDevice;
+ alsaDevice.start();
+ }
- 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);
- }
-
- // 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 @@
Slog.d(TAG, " alsaDevice:" + alsaDevice);
}
if (alsaDevice != null) {
- notifyDeviceState(alsaDevice, true /*enabled*/);
+ selectAlsaDevice(alsaDevice);
}
return alsaDevice;
} else {
@@ -202,16 +176,21 @@
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 @@
}
}
- /* 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 @@
// 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 6806947..a7fc470 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 @@
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 5fcff18..024bd30 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -29,7 +29,6 @@
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 @@
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 @@
}
/**
- * 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>
- * When setting the connection elapsed time, you should always set the connection time via
+ * 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 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 @@
* @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 d8599e8..3229705 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -2299,7 +2299,7 @@
*
* @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 211699e..1547857 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -21,7 +21,6 @@
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 @@
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 e301eb1..dc2ed43 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -102,6 +102,7 @@
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 3dbb503..a78b1a2 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -105,6 +105,7 @@
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 @@
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++) {