summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--api/current.txt1
-rw-r--r--cmds/bootanimation/bootanim.rc1
-rw-r--r--cmds/statsd/benchmark/metric_util.cpp5
-rw-r--r--cmds/statsd/src/StatsLogProcessor.cpp79
-rw-r--r--cmds/statsd/src/StatsLogProcessor.h15
-rw-r--r--cmds/statsd/src/StatsService.cpp98
-rw-r--r--cmds/statsd/src/StatsService.h15
-rw-r--r--cmds/statsd/src/config/ConfigManager.cpp12
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.cpp49
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.h19
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.cpp2
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp14
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.h7
-rw-r--r--cmds/statsd/src/stats_log.proto2
-rw-r--r--cmds/statsd/tests/StatsLogProcessor_test.cpp18
-rw-r--r--cmds/statsd/tests/UidMap_test.cpp3
-rw-r--r--cmds/statsd/tests/guardrail/StatsdStats_test.cpp23
-rw-r--r--cmds/statsd/tests/statsd_test_util.cpp5
-rw-r--r--core/java/android/app/LoadedApk.java10
-rw-r--r--core/java/android/hardware/display/DisplayManagerGlobal.java32
-rw-r--r--core/java/android/net/NetworkStack.java30
-rw-r--r--core/java/android/os/AsyncTask.java52
-rw-r--r--core/java/android/os/IStatsCompanionService.aidl6
-rw-r--r--core/java/android/provider/Settings.java2
-rw-r--r--core/jni/Android.bp4
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java1
-rw-r--r--libs/hwui/FrameMetricsObserver.h2
-rw-r--r--media/Android.bp13
-rw-r--r--media/apex/java/android/media/MediaPlayer2.java2
-rw-r--r--media/proto/jarjar-rules.txt2
-rw-r--r--packages/SettingsLib/common.mk1
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java34
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java36
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java117
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/DefaultClockSupplier.java101
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/SettingsWrapper.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java75
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/clock/DefaultClockSupplierTest.java132
-rw-r--r--services/core/java/com/android/server/ExtconUEventObserver.java46
-rw-r--r--services/core/java/com/android/server/WiredAccessoryManager.java155
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java13
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java2
-rw-r--r--services/core/java/com/android/server/media/MediaSessionServiceImpl.java26
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java10
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java60
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java4
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java17
-rw-r--r--services/core/java/com/android/server/wm/InputManagerCallback.java11
-rw-r--r--services/core/java/com/android/server/wm/RootActivityContainer.java5
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java3
-rw-r--r--telephony/java/android/telephony/CellIdentityNr.java21
-rw-r--r--telephony/java/android/telephony/NetworkRegistrationState.java39
-rw-r--r--telephony/java/android/telephony/ServiceState.java18
56 files changed, 953 insertions, 567 deletions
diff --git a/Android.bp b/Android.bp
index 9602941adc1c..8947cfae00bb 100644
--- a/Android.bp
+++ b/Android.bp
@@ -744,7 +744,6 @@ java_defaults {
"apex_aidl_interface-java",
"framework-protos",
"game-driver-protos",
- "mediaplayer2-protos",
"android.hidl.base-V1.0-java",
"android.hardware.cas-V1.1-java",
"android.hardware.cas-V1.0-java",
diff --git a/api/current.txt b/api/current.txt
index 921cfb5b14aa..16bc8c8cf804 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -44381,6 +44381,7 @@ package android.telephony {
method public int getChannelNumber();
method public String getMccString();
method public String getMncString();
+ method public long getNci();
method public int getPci();
method public int getTac();
method public void writeToParcel(android.os.Parcel, int);
diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc
index 1b3c32b20503..469c9646a4aa 100644
--- a/cmds/bootanimation/bootanim.rc
+++ b/cmds/bootanimation/bootanim.rc
@@ -2,7 +2,6 @@ service bootanim /system/bin/bootanimation
class core animation
user graphics
group graphics audio
- updatable
disabled
oneshot
writepid /dev/stune/top-app/tasks
diff --git a/cmds/statsd/benchmark/metric_util.cpp b/cmds/statsd/benchmark/metric_util.cpp
index 067b6eddf254..cca6d525ea16 100644
--- a/cmds/statsd/benchmark/metric_util.cpp
+++ b/cmds/statsd/benchmark/metric_util.cpp
@@ -367,7 +367,8 @@ sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const Stat
sp<AlarmMonitor> periodicAlarmMonitor;
sp<StatsLogProcessor> processor =
new StatsLogProcessor(uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec * NS_PER_SEC, [](const ConfigKey&) { return true; });
+ timeBaseSec * NS_PER_SEC, [](const ConfigKey&) { return true; },
+ [](const int&, const vector<int64_t>&) { return true; });
processor->OnConfigUpdated(timeBaseSec * NS_PER_SEC, key, config);
return processor;
}
@@ -393,4 +394,4 @@ int64_t StringToId(const string& str) {
} // namespace statsd
} // namespace os
-} // namespace android \ No newline at end of file
+} // namespace android
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index dd18bd4cc8ad..653ef2ec9869 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -88,12 +88,15 @@ StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor,
const int64_t timeBaseNs,
- const std::function<bool(const ConfigKey&)>& sendBroadcast)
+ const std::function<bool(const ConfigKey&)>& sendBroadcast,
+ const std::function<bool(
+ const int&, const vector<int64_t>&)>& activateBroadcast)
: mUidMap(uidMap),
mPullerManager(pullerManager),
mAnomalyAlarmMonitor(anomalyAlarmMonitor),
mPeriodicAlarmMonitor(periodicAlarmMonitor),
mSendBroadcast(sendBroadcast),
+ mSendActivationBroadcast(activateBroadcast),
mTimeBaseNs(timeBaseNs),
mLargestTimestampSeen(0),
mLastTimestampSeen(0) {
@@ -223,11 +226,73 @@ void StatsLogProcessor::OnLogEvent(LogEvent* event) {
mapIsolatedUidToHostUidIfNecessaryLocked(event);
}
+ std::unordered_set<int> uidsWithActiveConfigsChanged;
+ std::unordered_map<int, std::vector<int64_t>> activeConfigsPerUid;
// pass the event to metrics managers.
for (auto& pair : mMetricsManagers) {
+ int uid = pair.first.GetUid();
+ int64_t configId = pair.first.GetId();
+ bool isPrevActive = pair.second->isActive();
pair.second->onLogEvent(*event);
+ bool isCurActive = pair.second->isActive();
+ // Map all active configs by uid.
+ if (isCurActive) {
+ auto activeConfigs = activeConfigsPerUid.find(uid);
+ if (activeConfigs != activeConfigsPerUid.end()) {
+ activeConfigs->second.push_back(configId);
+ } else {
+ vector<int64_t> newActiveConfigs;
+ newActiveConfigs.push_back(configId);
+ activeConfigsPerUid[uid] = newActiveConfigs;
+ }
+ }
+ // The activation state of this config changed.
+ if (isPrevActive != isCurActive) {
+ VLOG("Active status changed for uid %d", uid);
+ uidsWithActiveConfigsChanged.insert(uid);
+ StatsdStats::getInstance().noteActiveStatusChanged(pair.first, isCurActive);
+ }
flushIfNecessaryLocked(event->GetElapsedTimestampNs(), pair.first, *(pair.second));
}
+
+ for (int uid : uidsWithActiveConfigsChanged) {
+ // Send broadcast so that receivers can pull data.
+ auto lastBroadcastTime = mLastActivationBroadcastTimes.find(uid);
+ if (lastBroadcastTime != mLastActivationBroadcastTimes.end()) {
+ if (currentTimestampNs - lastBroadcastTime->second <
+ StatsdStats::kMinActivationBroadcastPeriodNs) {
+ VLOG("StatsD would've sent an activation broadcast but the rate limit stopped us.");
+ return;
+ }
+ }
+ auto activeConfigs = activeConfigsPerUid.find(uid);
+ if (activeConfigs != activeConfigsPerUid.end()) {
+ if (mSendActivationBroadcast(uid, activeConfigs->second)) {
+ VLOG("StatsD sent activation notice for uid %d", uid);
+ mLastActivationBroadcastTimes[uid] = currentTimestampNs;
+ }
+ } else {
+ std::vector<int64_t> emptyActiveConfigs;
+ if (mSendActivationBroadcast(uid, emptyActiveConfigs)) {
+ VLOG("StatsD sent EMPTY activation notice for uid %d", uid);
+ mLastActivationBroadcastTimes[uid] = currentTimestampNs;
+ }
+ }
+ }
+}
+
+void StatsLogProcessor::GetActiveConfigs(const int uid, vector<int64_t>& outActiveConfigs) {
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
+ GetActiveConfigsLocked(uid, outActiveConfigs);
+}
+
+void StatsLogProcessor::GetActiveConfigsLocked(const int uid, vector<int64_t>& outActiveConfigs) {
+ outActiveConfigs.clear();
+ for (auto& pair : mMetricsManagers) {
+ if (pair.first.GetUid() == uid && pair.second->isActive()) {
+ outActiveConfigs.push_back(pair.first.GetId());
+ }
+ }
}
void StatsLogProcessor::OnConfigUpdated(const int64_t timestampNs, const ConfigKey& key,
@@ -444,6 +509,18 @@ void StatsLogProcessor::OnConfigRemoved(const ConfigKey& key) {
mLastBroadcastTimes.erase(key);
+ int uid = key.GetUid();
+ bool lastConfigForUid = true;
+ for (auto it : mMetricsManagers) {
+ if (it.first.GetUid() == uid) {
+ lastConfigForUid = false;
+ break;
+ }
+ }
+ if (lastConfigForUid) {
+ mLastActivationBroadcastTimes.erase(uid);
+ }
+
if (mMetricsManagers.empty()) {
mPullerManager->ForceClearPullerCache();
}
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index caf1a713986d..ea9c6e704017 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -49,7 +49,9 @@ public:
const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& subscriberTriggerAlarmMonitor,
const int64_t timeBaseNs,
- const std::function<bool(const ConfigKey&)>& sendBroadcast);
+ const std::function<bool(const ConfigKey&)>& sendBroadcast,
+ const std::function<bool(const int&,
+ const vector<int64_t>&)>& sendActivationBroadcast);
virtual ~StatsLogProcessor();
void OnLogEvent(LogEvent* event);
@@ -60,6 +62,8 @@ public:
size_t GetMetricsSize(const ConfigKey& key) const;
+ void GetActiveConfigs(const int uid, vector<int64_t>& outActiveConfigs);
+
void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs,
const bool include_current_partial_bucket, const bool erase_data,
const DumpReportReason dumpReportReason, vector<uint8_t>* outData);
@@ -125,6 +129,9 @@ private:
std::unordered_map<ConfigKey, long> mLastBroadcastTimes;
+ // Last time we sent a broadcast to this uid that the active configs had changed.
+ std::unordered_map<int, long> mLastActivationBroadcastTimes;
+
// Tracks when we last checked the bytes consumed for each config key.
std::unordered_map<ConfigKey, long> mLastByteSizeTimes;
@@ -144,6 +151,8 @@ private:
void OnConfigUpdatedLocked(
const int64_t currentTimestampNs, const ConfigKey& key, const StatsdConfig& config);
+ void GetActiveConfigsLocked(const int uid, vector<int64_t>& outActiveConfigs);
+
void WriteDataToDiskLocked(const DumpReportReason dumpReportReason);
void WriteDataToDiskLocked(const ConfigKey& key, const int64_t timestampNs,
const DumpReportReason dumpReportReason);
@@ -174,6 +183,10 @@ private:
// to retrieve the stored data.
std::function<bool(const ConfigKey& key)> mSendBroadcast;
+ // Function used to send a broadcast so that receiver can be notified of which configs
+ // are currently active.
+ std::function<bool(const int& uid, const vector<int64_t>& configIds)> mSendActivationBroadcast;
+
const int64_t mTimeBaseNs;
// Largest timestamp of the events that we have processed.
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index bd21a955729d..b478fed49a54 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -176,6 +176,21 @@ StatsService::StatsService(const sp<Looper>& handlerLooper)
sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key));
return true;
}
+ },
+ [this](const int& uid, const vector<int64_t>& activeConfigs) {
+ auto receiver = mConfigManager->GetActiveConfigsChangedReceiver(uid);
+ sp<IStatsCompanionService> sc = getStatsCompanionService();
+ if (sc == nullptr) {
+ VLOG("Could not access statsCompanion");
+ return false;
+ } else if (receiver == nullptr) {
+ VLOG("Could not find receiver for uid %d", uid);
+ return false;
+ } else {
+ sc->sendActiveConfigsChangedBroadcast(receiver, activeConfigs);
+ VLOG("StatsService::active configs broadcast succeeded for uid %d" , uid);
+ return true;
+ }
});
mConfigManager->AddListener(mProcessor);
@@ -357,6 +372,9 @@ status_t StatsService::command(int in, int out, int err, Vector<String8>& args,
if (!args[0].compare(String8("print-logs"))) {
return cmd_print_logs(out, args);
}
+ if (!args[0].compare(String8("send-active-configs"))) {
+ return cmd_trigger_active_config_broadcast(out, args);
+ }
if (!args[0].compare(String8("data-subscribe"))) {
if (mShellSubscriber == nullptr) {
mShellSubscriber = new ShellSubscriber(mUidMap, mPullerManager);
@@ -449,6 +467,19 @@ void StatsService::print_cmd_help(int out) {
dprintf(out, " NAME The name of the configuration\n");
dprintf(out, "\n");
dprintf(out, "\n");
+ dprintf(out,
+ "usage: adb shell cmd stats send-active-configs [--uid=UID] [--configs] "
+ "[NAME1] [NAME2] [NAME3..]\n");
+ dprintf(out, " Send a broadcast that informs the subscriber of the current active configs.\n");
+ dprintf(out, " --uid=UID The uid of the configurations. It is only possible to pass\n");
+ dprintf(out, " the UID parameter on eng builds. If UID is omitted the\n");
+ dprintf(out, " calling uid is used.\n");
+ dprintf(out, " --configs Send the list of configs in the name list instead of\n");
+ dprintf(out, " the currently active configs\n");
+ dprintf(out, " NAME LIST List of configuration names to be included in the broadcast.\n");
+
+ dprintf(out, "\n");
+ dprintf(out, "\n");
dprintf(out, "usage: adb shell cmd stats print-stats\n");
dprintf(out, " Prints some basic stats.\n");
dprintf(out, " --proto Print proto binary instead of string format.\n");
@@ -499,6 +530,59 @@ status_t StatsService::cmd_trigger_broadcast(int out, Vector<String8>& args) {
return NO_ERROR;
}
+status_t StatsService::cmd_trigger_active_config_broadcast(int out, Vector<String8>& args) {
+ const int argCount = args.size();
+ int uid;
+ vector<int64_t> configIds;
+ if (argCount == 1) {
+ // Automatically pick the uid and send a broadcast that has no active configs.
+ uid = IPCThreadState::self()->getCallingUid();
+ mProcessor->GetActiveConfigs(uid, configIds);
+ } else {
+ int curArg = 1;
+ if(args[curArg].find("--uid=") == 0) {
+ string uidArgStr(args[curArg].c_str());
+ string uidStr = uidArgStr.substr(6);
+ if (!getUidFromString(uidStr.c_str(), uid)) {
+ dprintf(out, "Invalid UID. Note that the config can only be set for "
+ "other UIDs on eng or userdebug builds.\n");
+ return UNKNOWN_ERROR;
+ }
+ curArg++;
+ } else {
+ uid = IPCThreadState::self()->getCallingUid();
+ }
+ if (curArg == argCount || args[curArg] != "--configs") {
+ VLOG("Reached end of args, or specify configs not set. Sending actual active configs,");
+ mProcessor->GetActiveConfigs(uid, configIds);
+ } else {
+ // Flag specified, use the given list of configs.
+ curArg++;
+ for (int i = curArg; i < argCount; i++) {
+ char* endp;
+ int64_t configID = strtoll(args[i].c_str(), &endp, 10);
+ if (endp == args[i].c_str() || *endp != '\0') {
+ dprintf(out, "Error parsing config ID.\n");
+ return UNKNOWN_ERROR;
+ }
+ VLOG("Adding config id %ld", static_cast<long>(configID));
+ configIds.push_back(configID);
+ }
+ }
+ }
+ auto receiver = mConfigManager->GetActiveConfigsChangedReceiver(uid);
+ sp<IStatsCompanionService> sc = getStatsCompanionService();
+ if (sc == nullptr) {
+ VLOG("Could not access statsCompanion");
+ } else if (receiver == nullptr) {
+ VLOG("Could not find receiver for uid %d", uid);
+ } else {
+ sc->sendActiveConfigsChangedBroadcast(receiver, configIds);
+ VLOG("StatsService::trigger active configs changed broadcast succeeded for uid %d" , uid);
+ }
+ return NO_ERROR;
+}
+
status_t StatsService::cmd_config(int in, int out, int err, Vector<String8>& args) {
const int argCount = args.size();
if (argCount >= 2) {
@@ -762,7 +846,10 @@ status_t StatsService::cmd_print_logs(int out, const Vector<String8>& args) {
}
bool StatsService::getUidFromArgs(const Vector<String8>& args, size_t uidArgIndex, int32_t& uid) {
- const char* s = args[uidArgIndex].c_str();
+ return getUidFromString(args[uidArgIndex].c_str(), uid);
+}
+
+bool StatsService::getUidFromString(const char* s, int32_t& uid) {
if (*s == '\0') {
return false;
}
@@ -998,8 +1085,13 @@ Status StatsService::setActiveConfigsChangedOperation(const sp<android::IBinder>
ENFORCE_DUMP_AND_USAGE_STATS(packageName);
IPCThreadState* ipc = IPCThreadState::self();
- mConfigManager->SetActiveConfigsChangedReceiver(ipc->getCallingUid(), intentSender);
- //TODO: Return the list of configs that are already active
+ int uid = ipc->getCallingUid();
+ mConfigManager->SetActiveConfigsChangedReceiver(uid, intentSender);
+ if (output != nullptr) {
+ mProcessor->GetActiveConfigs(uid, *output);
+ } else {
+ ALOGW("StatsService::setActiveConfigsChanged output was nullptr");
+ }
return Status::ok();
}
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 941ed462b303..7f10d74ec7d6 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -275,6 +275,12 @@ private:
*/
status_t cmd_trigger_broadcast(int outFd, Vector<String8>& args);
+
+ /**
+ * Trigger an active configs changed broadcast.
+ */
+ status_t cmd_trigger_active_config_broadcast(int outFd, Vector<String8>& args);
+
/**
* Handle the config sub-command.
*/
@@ -341,6 +347,15 @@ private:
bool getUidFromArgs(const Vector<String8>& args, size_t uidArgIndex, int32_t& uid);
/**
+ * Writes the value of uidSting into uid.
+ * Returns whether the uid is reasonable (type uid_t) and whether
+ * 1. it is equal to the calling uid, or
+ * 2. the device is mEngBuild, or
+ * 3. the caller is AID_ROOT and the uid is AID_SHELL (i.e. ROOT can impersonate SHELL).
+ */
+ bool getUidFromString(const char* uidString, int32_t& uid);
+
+ /**
* Adds a configuration after checking permissions and obtaining UID from binder call.
*/
bool addConfigurationChecked(int uid, int64_t key, const vector<uint8_t>& config);
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index aa22333ab26c..fc949b494194 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -144,10 +144,20 @@ void ConfigManager::RemoveConfig(const ConfigKey& key) {
{
lock_guard <mutex> lock(mMutex);
- auto uidIt = mConfigs.find(key.GetUid());
+ auto uid = key.GetUid();
+ auto uidIt = mConfigs.find(uid);
if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end()) {
// Remove from map
uidIt->second.erase(key);
+
+ // No more configs for this uid, lets remove the active configs callback.
+ if (uidIt->second.empty()) {
+ auto itActiveConfigsChangedReceiver = mActiveConfigsChangedReceivers.find(uid);
+ if (itActiveConfigsChangedReceiver != mActiveConfigsChangedReceivers.end()) {
+ mActiveConfigsChangedReceivers.erase(itActiveConfigsChangedReceiver);
+ }
+ }
+
for (const sp<ConfigListener>& listener : mListeners) {
broadcastList.push_back(listener);
}
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 40329b7c86ab..b433c41518cc 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -82,6 +82,8 @@ const int FIELD_ID_CONFIG_STATS_METRIC_STATS = 15;
const int FIELD_ID_CONFIG_STATS_ALERT_STATS = 16;
const int FIELD_ID_CONFIG_STATS_METRIC_DIMENSION_IN_CONDITION_STATS = 17;
const int FIELD_ID_CONFIG_STATS_ANNOTATION = 18;
+const int FIELD_ID_CONFIG_STATS_ACTIVATION = 22;
+const int FIELD_ID_CONFIG_STATS_DEACTIVATION = 23;
const int FIELD_ID_CONFIG_STATS_ANNOTATION_INT64 = 1;
const int FIELD_ID_CONFIG_STATS_ANNOTATION_INT32 = 2;
@@ -206,6 +208,25 @@ void StatsdStats::noteBroadcastSent(const ConfigKey& key, int32_t timeSec) {
it->second->broadcast_sent_time_sec.push_back(timeSec);
}
+void StatsdStats::noteActiveStatusChanged(const ConfigKey& key, bool activated) {
+ noteActiveStatusChanged(key, activated, getWallClockSec());
+}
+
+void StatsdStats::noteActiveStatusChanged(const ConfigKey& key, bool activated, int32_t timeSec) {
+ lock_guard<std::mutex> lock(mLock);
+ auto it = mConfigStats.find(key);
+ if (it == mConfigStats.end()) {
+ ALOGE("Config key %s not found!", key.ToString().c_str());
+ return;
+ }
+ auto& vec = activated ? it->second->activation_time_sec
+ : it->second->deactivation_time_sec;
+ if (vec.size() == kMaxTimestampCount) {
+ vec.pop_front();
+ }
+ vec.push_back(timeSec);
+}
+
void StatsdStats::noteDataDropped(const ConfigKey& key, const size_t totalBytes) {
noteDataDropped(key, totalBytes, getWallClockSec());
}
@@ -501,6 +522,8 @@ void StatsdStats::resetInternalLocked() {
mLogLossStats.clear();
for (auto& config : mConfigStats) {
config.second->broadcast_sent_time_sec.clear();
+ config.second->activation_time_sec.clear();
+ config.second->deactivation_time_sec.clear();
config.second->data_drop_time_sec.clear();
config.second->data_drop_bytes.clear();
config.second->dump_report_stats.clear();
@@ -558,6 +581,14 @@ void StatsdStats::dumpStats(int out) const {
dprintf(out, "\tbroadcast time: %d\n", broadcastTime);
}
+ for (const int& activationTime : configStats->activation_time_sec) {
+ dprintf(out, "\tactivation time: %d\n", activationTime);
+ }
+
+ for (const int& deactivationTime : configStats->deactivation_time_sec) {
+ dprintf(out, "\tdeactivation time: %d\n", deactivationTime);
+ }
+
auto dropTimePtr = configStats->data_drop_time_sec.begin();
auto dropBytesPtr = configStats->data_drop_bytes.begin();
for (int i = 0; i < (int)configStats->data_drop_time_sec.size();
@@ -586,6 +617,14 @@ void StatsdStats::dumpStats(int out) const {
(long long)broadcastTime);
}
+ for (const int& activationTime : configStats->activation_time_sec) {
+ dprintf(out, "\tactivation time: %d\n", activationTime);
+ }
+
+ for (const int& deactivationTime : configStats->deactivation_time_sec) {
+ dprintf(out, "\tdeactivation time: %d\n", deactivationTime);
+ }
+
auto dropTimePtr = configStats->data_drop_time_sec.begin();
auto dropBytesPtr = configStats->data_drop_bytes.begin();
for (int i = 0; i < (int)configStats->data_drop_time_sec.size();
@@ -696,6 +735,16 @@ void addConfigStatsToProto(const ConfigStats& configStats, ProtoOutputStream* pr
broadcast);
}
+ for (const auto& activation : configStats.activation_time_sec) {
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_ACTIVATION | FIELD_COUNT_REPEATED,
+ activation);
+ }
+
+ for (const auto& deactivation : configStats.deactivation_time_sec) {
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DEACTIVATION | FIELD_COUNT_REPEATED,
+ deactivation);
+ }
+
for (const auto& drop_time : configStats.data_drop_time_sec) {
proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DATA_DROP_TIME | FIELD_COUNT_REPEATED,
drop_time);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 65e8a324d7d3..5275c8f34fd0 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -42,6 +42,13 @@ struct ConfigStats {
bool is_valid;
std::list<int32_t> broadcast_sent_time_sec;
+
+ // Times at which this config is activated.
+ std::list<int32_t> activation_time_sec;
+
+ // Times at which this config is deactivated.
+ std::list<int32_t> deactivation_time_sec;
+
std::list<int32_t> data_drop_time_sec;
// Number of bytes dropped at corresponding time.
std::list<int64_t> data_drop_bytes;
@@ -132,6 +139,9 @@ public:
/* Min period between two checks of byte size per config key in nanoseconds. */
static const int64_t kMinByteSizeCheckPeriodNs = 60 * NS_PER_SEC;
+ /* Minimum period between two activation broadcasts in nanoseconds. */
+ static const int64_t kMinActivationBroadcastPeriodNs = 10 * NS_PER_SEC;
+
// Maximum age (30 days) that files on disk can exist in seconds.
static const int kMaxAgeSecond = 60 * 60 * 24 * 30;
@@ -175,6 +185,13 @@ public:
void noteBroadcastSent(const ConfigKey& key);
/**
+ * Report that a config has become activated or deactivated.
+ * This can be different from whether or not a broadcast is sent if the
+ * guardrail prevented the broadcast from being sent.
+ */
+ void noteActiveStatusChanged(const ConfigKey& key, bool activate);
+
+ /**
* Report a config's metrics data has been dropped.
*/
void noteDataDropped(const ConfigKey& key, const size_t totalBytes);
@@ -507,6 +524,8 @@ private:
void noteBroadcastSent(const ConfigKey& key, int32_t timeSec);
+ void noteActiveStatusChanged(const ConfigKey& key, bool activate, int32_t timeSec);
+
void addToIceBoxLocked(std::shared_ptr<ConfigStats>& stats);
/**
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 495138ee9b77..11075685b7fa 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -94,7 +94,7 @@ void MetricProducer::flushIfExpire(int64_t elapsedTimestampNs) {
void MetricProducer::addActivation(int activationTrackerIndex, int64_t ttl_seconds) {
std::lock_guard<std::mutex> lock(mMutex);
// When a metric producer does not depend on any activation, its mIsActive is true.
- // Therefor, if this is the 1st activation, mIsActive will turn to false. Otherwise it does not
+ // Therefore, if this is the 1st activation, mIsActive will turn to false. Otherwise it does not
// change.
if (mEventActivationMap.empty()) {
mIsActive = false;
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 6ed6ab500597..4851a8d40baa 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -118,6 +118,16 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
ALOGE("This config has too many alerts! Reject!");
mConfigValid = false;
}
+
+ mIsAlwaysActive = (mMetricIndexesWithActivation.size() != mAllMetricProducers.size()) ||
+ (mAllMetricProducers.size() == 0);
+ bool isActive = mIsAlwaysActive;
+ for (int metric : mMetricIndexesWithActivation) {
+ isActive |= mAllMetricProducers[metric]->isActive();
+ }
+ mIsActive = isActive;
+ VLOG("mIsActive is initialized to %d", mIsActive)
+
// no matter whether this config is valid, log it in the stats.
StatsdStats::getInstance().noteConfigReceived(
key, mAllMetricProducers.size(), mAllConditionTrackers.size(), mAllAtomMatchers.size(),
@@ -332,12 +342,14 @@ void MetricsManager::onLogEvent(const LogEvent& event) {
int tagId = event.GetTagId();
int64_t eventTimeNs = event.GetElapsedTimestampNs();
- bool isActive = false;
+ bool isActive = mIsAlwaysActive;
for (int metric : mMetricIndexesWithActivation) {
mAllMetricProducers[metric]->flushIfExpire(eventTimeNs);
isActive |= mAllMetricProducers[metric]->isActive();
}
+ mIsActive = isActive;
+
if (mTagIds.find(tagId) == mTagIds.end()) {
// not interesting...
return;
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index cb1cefbf2063..eab1f762b390 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -128,6 +128,8 @@ public:
// Does not change the state.
virtual size_t byteSize();
+ // Returns whether or not this config is active.
+ // The config is active if any metric in the config is active.
inline bool isActive() const {
return mIsActive;
}
@@ -241,9 +243,12 @@ private:
// The metrics that don't need to be uploaded or even reported.
std::set<int64_t> mNoReportMetricIds;
- // Any metric active means the config is active.
+ // The config is active if any metric in the config is active.
bool mIsActive;
+ // The config is always active if any metric in the config does not have an activation signal.
+ bool mIsAlwaysActive;
+
FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions);
FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 863261ae1626..f7428a50b3da 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -367,6 +367,8 @@ message StatsdStatsReport {
optional int32 field_int32 = 2;
}
repeated Annotation annotation = 18;
+ repeated int32 activation_time_sec = 22;
+ repeated int32 deactivation_time_sec = 23;
}
repeated ConfigStats config_stats = 3;
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 60df165f102c..5f3aae3ab93a 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -65,7 +65,8 @@ TEST(StatsLogProcessorTest, TestRateLimitByteSize) {
sp<AlarmMonitor> periodicAlarmMonitor;
// Construct the processor with a dummy sendBroadcast function that does nothing.
StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, 0,
- [](const ConfigKey& key) { return true; });
+ [](const ConfigKey& key) { return true; },
+ [](const int&, const vector<int64_t>&) {return true;});
MockMetricsManager mockMetricsManager;
@@ -88,7 +89,8 @@ TEST(StatsLogProcessorTest, TestRateLimitBroadcast) {
[&broadcastCount](const ConfigKey& key) {
broadcastCount++;
return true;
- });
+ },
+ [](const int&, const vector<int64_t>&) {return true;});
MockMetricsManager mockMetricsManager;
@@ -118,7 +120,8 @@ TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge) {
[&broadcastCount](const ConfigKey& key) {
broadcastCount++;
return true;
- });
+ },
+ [](const int&, const vector<int64_t>&) {return true;});
MockMetricsManager mockMetricsManager;
@@ -162,7 +165,8 @@ TEST(StatsLogProcessorTest, TestUidMapHasSnapshot) {
[&broadcastCount](const ConfigKey& key) {
broadcastCount++;
return true;
- });
+ },
+ [](const int&, const vector<int64_t>&) {return true;});
ConfigKey key(3, 4);
StatsdConfig config = MakeConfig(true);
p.OnConfigUpdated(0, key, config);
@@ -192,7 +196,8 @@ TEST(StatsLogProcessorTest, TestEmptyConfigHasNoUidMap) {
[&broadcastCount](const ConfigKey& key) {
broadcastCount++;
return true;
- });
+ },
+ [](const int&, const vector<int64_t>&) {return true;});
ConfigKey key(3, 4);
StatsdConfig config = MakeConfig(false);
p.OnConfigUpdated(0, key, config);
@@ -218,7 +223,8 @@ TEST(StatsLogProcessorTest, TestReportIncludesSubConfig) {
[&broadcastCount](const ConfigKey& key) {
broadcastCount++;
return true;
- });
+ },
+ [](const int&, const vector<int64_t>&) {return true;});
ConfigKey key(3, 4);
StatsdConfig config;
auto annotation = config.add_annotation();
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index f0d9cf188661..c04a40cfebd9 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -45,7 +45,8 @@ TEST(UidMapTest, TestIsolatedUID) {
sp<AlarmMonitor> subscriberAlarmMonitor;
// Construct the processor with a dummy sendBroadcast function that does nothing.
StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
- [](const ConfigKey& key) { return true; });
+ [](const ConfigKey& key) { return true; },
+ [](const int&, const vector<int64_t>&) {return true;});
LogEvent addEvent(android::util::ISOLATED_UID_CHANGED, 1);
addEvent.write(100); // parent UID
addEvent.write(101); // isolated UID
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 44a88f049443..1ff7982e1232 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -133,6 +133,13 @@ TEST(StatsdStatsTest, TestSubStats) {
stats.noteMetricsReportSent(key, 0);
stats.noteMetricsReportSent(key, 0);
+ // activation_time_sec -> 2
+ stats.noteActiveStatusChanged(key, true);
+ stats.noteActiveStatusChanged(key, true);
+
+ // deactivation_time_sec -> 1
+ stats.noteActiveStatusChanged(key, false);
+
vector<uint8_t> output;
stats.dumpStats(&output, true); // Dump and reset stats
StatsdStatsReport report;
@@ -146,6 +153,8 @@ TEST(StatsdStatsTest, TestSubStats) {
EXPECT_EQ(123, configReport.data_drop_bytes(0));
EXPECT_EQ(3, configReport.dump_report_time_sec_size());
EXPECT_EQ(3, configReport.dump_report_data_size_size());
+ EXPECT_EQ(2, configReport.activation_time_sec_size());
+ EXPECT_EQ(1, configReport.deactivation_time_sec_size());
EXPECT_EQ(1, configReport.annotation_size());
EXPECT_EQ(123, configReport.annotation(0).field_int64());
EXPECT_EQ(456, configReport.annotation(0).field_int32());
@@ -344,6 +353,8 @@ TEST(StatsdStatsTest, TestTimestampThreshold) {
stats.noteDataDropped(key, timestamps[i]);
stats.noteBroadcastSent(key, timestamps[i]);
stats.noteMetricsReportSent(key, 0, timestamps[i]);
+ stats.noteActiveStatusChanged(key, true, timestamps[i]);
+ stats.noteActiveStatusChanged(key, false, timestamps[i]);
}
int32_t newTimestamp = 10000;
@@ -352,6 +363,8 @@ TEST(StatsdStatsTest, TestTimestampThreshold) {
stats.noteDataDropped(key, 123, 10000);
stats.noteBroadcastSent(key, 10000);
stats.noteMetricsReportSent(key, 0, 10000);
+ stats.noteActiveStatusChanged(key, true, 10000);
+ stats.noteActiveStatusChanged(key, false, 10000);
EXPECT_TRUE(stats.mConfigStats.find(key) != stats.mConfigStats.end());
const auto& configStats = stats.mConfigStats[key];
@@ -360,17 +373,23 @@ TEST(StatsdStatsTest, TestTimestampThreshold) {
EXPECT_EQ(maxCount, configStats->broadcast_sent_time_sec.size());
EXPECT_EQ(maxCount, configStats->data_drop_time_sec.size());
EXPECT_EQ(maxCount, configStats->dump_report_stats.size());
+ EXPECT_EQ(maxCount, configStats->activation_time_sec.size());
+ EXPECT_EQ(maxCount, configStats->deactivation_time_sec.size());
// the oldest timestamp is the second timestamp in history
EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
- EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
- EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
+ EXPECT_EQ(1, configStats->data_drop_bytes.front());
+ EXPECT_EQ(1, configStats->dump_report_stats.front().first);
+ EXPECT_EQ(1, configStats->activation_time_sec.front());
+ EXPECT_EQ(1, configStats->deactivation_time_sec.front());
// the last timestamp is the newest timestamp.
EXPECT_EQ(newTimestamp, configStats->broadcast_sent_time_sec.back());
EXPECT_EQ(newTimestamp, configStats->data_drop_time_sec.back());
EXPECT_EQ(123, configStats->data_drop_bytes.back());
EXPECT_EQ(newTimestamp, configStats->dump_report_stats.back().first);
+ EXPECT_EQ(newTimestamp, configStats->activation_time_sec.back());
+ EXPECT_EQ(newTimestamp, configStats->deactivation_time_sec.back());
}
TEST(StatsdStatsTest, TestSystemServerCrash) {
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index b8b1a1db2c12..2c4f3c7692c9 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -461,7 +461,8 @@ sp<StatsLogProcessor> CreateStatsLogProcessor(const int64_t timeBaseNs, const in
[](const sp<IStatsCompanionService>&){});
sp<StatsLogProcessor> processor =
new StatsLogProcessor(uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseNs, [](const ConfigKey&) { return true; });
+ timeBaseNs, [](const ConfigKey&) { return true; },
+ [](const int&, const vector<int64_t>&) {return true;});
processor->OnConfigUpdated(currentTimeNs, key, config);
return processor;
}
@@ -826,4 +827,4 @@ void backfillStartEndTimestamp(ConfigMetricsReportList *config_report_list) {
} // namespace statsd
} // namespace os
-} // namespace android \ No newline at end of file
+} // namespace android
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index d46dbedfe8c2..5c4c0052cfbb 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -870,8 +870,9 @@ public final class LoadedApk {
}
}
- // /vendor/lib, /odm/lib and /product/lib are added to the native lib search
- // paths of the classloader. Note that this is done AFTER the classloader is
+ // /aepx/com.android.runtime/lib, /vendor/lib, /odm/lib and /product/lib
+ // are added to the native lib search paths of the classloader.
+ // Note that this is done AFTER the classloader is
// created by ApplicationLoaders.getDefault().getClassLoader(...). The
// reason is because if we have added the paths when creating the classloader
// above, the paths are also added to the search path of the linker namespace
@@ -888,8 +889,11 @@ public final class LoadedApk {
// System.loadLibrary(). In order to prevent the problem, we explicitly
// add the paths only to the classloader, and not to the native loader
// (linker namespace).
- List<String> extraLibPaths = new ArrayList<>(3);
+ List<String> extraLibPaths = new ArrayList<>(4);
String abiSuffix = VMRuntime.getRuntime().is64Bit() ? "64" : "";
+ if (!defaultSearchPaths.contains("/apex/com.android.runtime/lib")) {
+ extraLibPaths.add("/apex/com.android.runtime/lib" + abiSuffix);
+ }
if (!defaultSearchPaths.contains("/vendor/lib")) {
extraLibPaths.add("/vendor/lib" + abiSuffix);
}
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index f3ebd7f36fd6..ac44fe93ac31 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -16,6 +16,8 @@
package android.hardware.display;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ParceledListSlice;
@@ -229,7 +231,17 @@ public final class DisplayManagerGlobal {
return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
}
- public void registerDisplayListener(DisplayListener listener, Handler handler) {
+ /**
+ * Register a listener for display-related changes.
+ *
+ * @param listener The listener that will be called when display changes occur.
+ * @param handler Handler for the thread that will be receiving the callbacks. May be null.
+ * If null, listener will use the handler for the current thread, and if still null,
+ * the handler for the main thread.
+ * If that is still null, a runtime exception will be thrown.
+ */
+ public void registerDisplayListener(@NonNull DisplayListener listener,
+ @Nullable Handler handler) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}
@@ -237,7 +249,8 @@ public final class DisplayManagerGlobal {
synchronized (mLock) {
int index = findDisplayListenerLocked(listener);
if (index < 0) {
- mDisplayListeners.add(new DisplayListenerDelegate(listener, handler));
+ Looper looper = getLooperForHandler(handler);
+ mDisplayListeners.add(new DisplayListenerDelegate(listener, looper));
registerCallbackIfNeededLocked();
}
}
@@ -258,6 +271,17 @@ public final class DisplayManagerGlobal {
}
}
+ private static Looper getLooperForHandler(@Nullable Handler handler) {
+ Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
+ if (looper == null) {
+ looper = Looper.getMainLooper();
+ }
+ if (looper == null) {
+ throw new RuntimeException("Could not get Looper for the UI thread.");
+ }
+ return looper;
+ }
+
private int findDisplayListenerLocked(DisplayListener listener) {
final int numListeners = mDisplayListeners.size();
for (int i = 0; i < numListeners; i++) {
@@ -636,8 +660,8 @@ public final class DisplayManagerGlobal {
private static final class DisplayListenerDelegate extends Handler {
public final DisplayListener mListener;
- public DisplayListenerDelegate(DisplayListener listener, Handler handler) {
- super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
+ DisplayListenerDelegate(DisplayListener listener, @NonNull Looper looper) {
+ super(looper, null, true /*async*/);
mListener = listener;
}
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index 7a4c9bc16ac7..ca49438390e9 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -15,6 +15,7 @@
*/
package android.net;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
@@ -27,6 +28,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.IDhcpServerCallbacks;
import android.net.ip.IIpClientCallbacks;
@@ -201,7 +203,33 @@ public class NetworkStack {
final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
intent.setComponent(comp);
- if (comp == null || !context.bindServiceAsUser(intent, new NetworkStackConnection(),
+ if (comp == null) {
+ Slog.wtf(TAG, "Could not resolve the network stack with " + intent);
+ // TODO: crash/reboot system server ?
+ return;
+ }
+
+ final PackageManager pm = context.getPackageManager();
+ int uid = -1;
+ try {
+ uid = pm.getPackageUid(comp.getPackageName(), UserHandle.USER_SYSTEM);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.wtf("Network stack package not found", e);
+ // Fall through
+ }
+
+ if (uid != Process.NETWORK_STACK_UID) {
+ throw new SecurityException("Invalid network stack UID: " + uid);
+ }
+
+ final int hasPermission =
+ pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName());
+ if (hasPermission != PERMISSION_GRANTED) {
+ throw new SecurityException(
+ "Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK);
+ }
+
+ if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
Slog.wtf(TAG,
"Could not bind to network stack in-process, or in app with " + intent);
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 1f3369376b10..a851e04e78ec 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -21,13 +21,14 @@ import android.annotation.Nullable;
import android.annotation.WorkerThread;
import java.util.ArrayDeque;
-import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -190,13 +191,19 @@ import java.util.concurrent.atomic.AtomicInteger;
public abstract class AsyncTask<Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";
- private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
- // We want at least 2 threads and at most 4 threads in the core pool,
- // preferring to have 1 less than the CPU count to avoid saturating
- // the CPU with background work
- private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
- private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
- private static final int KEEP_ALIVE_SECONDS = 30;
+ // We keep only a single pool thread around all the time.
+ // We let the pool grow to a fairly large number of threads if necessary,
+ // but let them time out quickly. In the unlikely case that we run out of threads,
+ // we fall back to a simple unbounded-queue executor.
+ // This combination ensures that:
+ // 1. We normally keep few threads (1) around.
+ // 2. We queue only after launching a significantly larger, but still bounded, set of threads.
+ // 3. We keep the total number of threads bounded, but still allow an unbounded set
+ // of tasks to be queued.
+ private static final int CORE_POOL_SIZE = 1;
+ private static final int MAXIMUM_POOL_SIZE = 20;
+ private static final int BACKUP_POOL_SIZE = 5;
+ private static final int KEEP_ALIVE_SECONDS = 3;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
@@ -206,8 +213,29 @@ public abstract class AsyncTask<Params, Progress, Result> {
}
};
- private static final BlockingQueue<Runnable> sPoolWorkQueue =
- new LinkedBlockingQueue<Runnable>(128);
+ // Used only for rejected executions.
+ // Initialization protected by sRunOnSerialPolicy lock.
+ private static ThreadPoolExecutor sBackupExecutor;
+ private static LinkedBlockingQueue<Runnable> sBackupExecutorQueue;
+
+ private static final RejectedExecutionHandler sRunOnSerialPolicy =
+ new RejectedExecutionHandler() {
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
+ android.util.Log.w(LOG_TAG, "Exceeded ThreadPoolExecutor pool size");
+ // As a last ditch fallback, run it on an executor with an unbounded queue.
+ // Create this executor lazily, hopefully almost never.
+ synchronized (this) {
+ if (sBackupExecutor == null) {
+ sBackupExecutorQueue = new LinkedBlockingQueue<Runnable>();
+ sBackupExecutor = new ThreadPoolExecutor(
+ BACKUP_POOL_SIZE, BACKUP_POOL_SIZE, KEEP_ALIVE_SECONDS,
+ TimeUnit.SECONDS, sBackupExecutorQueue, sThreadFactory);
+ sBackupExecutor.allowCoreThreadTimeOut(true);
+ }
+ }
+ sBackupExecutor.execute(r);
+ }
+ };
/**
* An {@link Executor} that can be used to execute tasks in parallel.
@@ -217,8 +245,8 @@ public abstract class AsyncTask<Params, Progress, Result> {
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
- sPoolWorkQueue, sThreadFactory);
- threadPoolExecutor.allowCoreThreadTimeOut(true);
+ new SynchronousQueue<Runnable>(), sThreadFactory);
+ threadPoolExecutor.setRejectedExecutionHandler(sRunOnSerialPolicy);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
diff --git a/core/java/android/os/IStatsCompanionService.aidl b/core/java/android/os/IStatsCompanionService.aidl
index dde46cd93d5f..0751b964f85e 100644
--- a/core/java/android/os/IStatsCompanionService.aidl
+++ b/core/java/android/os/IStatsCompanionService.aidl
@@ -69,6 +69,12 @@ interface IStatsCompanionService {
oneway void sendDataBroadcast(in IBinder intentSender, long lastReportTimeNs);
/**
+ * Send a broadcast to the specified PendingIntent's as IBinder notifying it that the list
+ * of active configs has changed.
+ */
+ oneway void sendActiveConfigsChangedBroadcast(in IBinder intentSender, in long[] configIds);
+
+ /**
* Requests StatsCompanionService to send a broadcast using the given intentSender
* (which should cast to an IIntentSender), along with the other information specified.
*/
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7f59d35586c1..2b638f6e283f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6103,7 +6103,7 @@ public final class Settings {
* Indicates which clock face to show on lock screen and AOD while docked.
* @hide
*/
- public static final String DOCKED_CLOCK_FACE = "docked_clock_face";
+ private static final String DOCKED_CLOCK_FACE = "docked_clock_face";
/**
* Set by the system to track if the user needs to see the call to action for
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 345058bd4f6f..af0b7c307ef6 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -287,8 +287,8 @@ cc_library_shared {
"libsoundtrigger",
"libminikin",
"libprocessgroup",
- "libnativebridge",
- "libnativeloader",
+ "libnativebridge_lazy",
+ "libnativeloader_lazy",
"libmemunreachable",
"libhidlbase",
"libhidltransport",
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index c57b609023ca..4d2f005998c3 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -621,7 +621,6 @@ public class SettingsBackupTest {
Settings.Secure.DISABLED_PRINT_SERVICES,
Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS,
Settings.Secure.DISPLAY_DENSITY_FORCED,
- Settings.Secure.DOCKED_CLOCK_FACE,
Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION,
Settings.Secure.ENABLED_INPUT_METHODS, // Intentionally removed in P
diff --git a/libs/hwui/FrameMetricsObserver.h b/libs/hwui/FrameMetricsObserver.h
index 237fc622dd2e..b93f07853242 100644
--- a/libs/hwui/FrameMetricsObserver.h
+++ b/libs/hwui/FrameMetricsObserver.h
@@ -23,7 +23,7 @@ namespace uirenderer {
class FrameMetricsObserver : public VirtualLightRefBase {
public:
- virtual void notify(const int64_t* buffer);
+ virtual void notify(const int64_t* buffer) = 0;
};
} // namespace uirenderer
diff --git a/media/Android.bp b/media/Android.bp
index 141d415cbaf3..86dc509501a4 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -3,7 +3,6 @@ java_library {
srcs: [
":updatable-media-srcs",
- ":framework-media-annotation-srcs",
],
aidl: {
@@ -28,7 +27,12 @@ java_library {
installable: true,
// Make sure that the implementaion only relies on SDK or system APIs.
- sdk_version: "system_current",
+ no_framework_libs: true,
+ libs: [
+ // The order matters. android_system_* library should come later.
+ "framework_media_annotation",
+ "android_system_stubs_current",
+ ],
}
filegroup {
@@ -125,3 +129,8 @@ java_library {
sdk_version: "28",
}
+java_library {
+ name: "framework_media_annotation",
+ srcs: [":framework-media-annotation-srcs"],
+ installable: false,
+}
diff --git a/media/apex/java/android/media/MediaPlayer2.java b/media/apex/java/android/media/MediaPlayer2.java
index c38a83131a6c..89a954061958 100644
--- a/media/apex/java/android/media/MediaPlayer2.java
+++ b/media/apex/java/android/media/MediaPlayer2.java
@@ -45,8 +45,8 @@ import android.util.Size;
import android.view.Surface;
import android.view.SurfaceHolder;
-import com.android.framework.protobuf.InvalidProtocolBufferException;
import com.android.internal.annotations.GuardedBy;
+import com.android.media.protobuf.InvalidProtocolBufferException;
import java.io.ByteArrayOutputStream;
import java.io.File;
diff --git a/media/proto/jarjar-rules.txt b/media/proto/jarjar-rules.txt
index 7be6e732d3fd..bfb0b2782486 100644
--- a/media/proto/jarjar-rules.txt
+++ b/media/proto/jarjar-rules.txt
@@ -1,2 +1,2 @@
-rule com.google.protobuf.** com.android.framework.protobuf.@1
+rule com.google.protobuf.** com.android.media.protobuf.@1
diff --git a/packages/SettingsLib/common.mk b/packages/SettingsLib/common.mk
index 8c309ff97370..8d24eaba5cc4 100644
--- a/packages/SettingsLib/common.mk
+++ b/packages/SettingsLib/common.mk
@@ -31,3 +31,4 @@ LOCAL_STATIC_ANDROID_LIBRARIES += \
androidx.legacy_legacy-preference-v14 \
SettingsLib
+LOCAL_RESOURCE_DIR += $(call my-dir)/res
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
index 305a1ff97e71..dd6d563b3197 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
@@ -40,6 +40,7 @@ import androidx.loader.content.AsyncTaskLoader;
import com.android.settingslib.NetworkPolicyEditor;
import java.time.ZonedDateTime;
+import java.util.ArrayList;
import java.util.Iterator;
/**
@@ -52,6 +53,7 @@ public abstract class NetworkCycleDataLoader<D> extends AsyncTaskLoader<D> {
protected final int mNetworkType;
private final NetworkPolicy mPolicy;
private final NetworkTemplate mNetworkTemplate;
+ private final ArrayList<Long> mCycles;
@VisibleForTesting
final INetworkStatsService mNetworkStatsService;
@@ -60,6 +62,7 @@ public abstract class NetworkCycleDataLoader<D> extends AsyncTaskLoader<D> {
mSubId = builder.mSubId;
mNetworkType = builder.mNetworkType;
mNetworkTemplate = builder.mNetworkTemplate;
+ mCycles = builder.mCycles;
mNetworkStatsManager = (NetworkStatsManager)
builder.mContext.getSystemService(Context.NETWORK_STATS_SERVICE);
mNetworkStatsService = INetworkStatsService.Stub.asInterface(
@@ -77,7 +80,9 @@ public abstract class NetworkCycleDataLoader<D> extends AsyncTaskLoader<D> {
}
public D loadInBackground() {
- if (mPolicy == null) {
+ if (mCycles != null && mCycles.size() > 1) {
+ loadDataForSpecificCycles();
+ } else if (mPolicy == null) {
loadFourWeeksData();
} else {
loadPolicyData();
@@ -132,6 +137,17 @@ public abstract class NetworkCycleDataLoader<D> extends AsyncTaskLoader<D> {
}
@VisibleForTesting
+ void loadDataForSpecificCycles() {
+ long cycleEnd = mCycles.get(0);
+ final int lastCycleIndex = mCycles.size() - 1;
+ for (int i = 1; i <= lastCycleIndex; i++) {
+ final long cycleStart = mCycles.get(i);
+ recordUsage(cycleStart, cycleEnd);
+ cycleEnd = cycleStart;
+ }
+ }
+
+ @VisibleForTesting
abstract void recordUsage(long start, long end);
abstract D getCycleUsage();
@@ -157,11 +173,17 @@ public abstract class NetworkCycleDataLoader<D> extends AsyncTaskLoader<D> {
return bytes;
}
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ public ArrayList<Long> getCycles() {
+ return mCycles;
+ }
+
public static abstract class Builder<T extends NetworkCycleDataLoader> {
private final Context mContext;
private String mSubId;
private int mNetworkType;
private NetworkTemplate mNetworkTemplate;
+ private ArrayList<Long> mCycles;
public Builder (Context context) {
mContext = context;
@@ -178,6 +200,16 @@ public abstract class NetworkCycleDataLoader<D> extends AsyncTaskLoader<D> {
return this;
}
+ /**
+ * Sets the network cycles to be used to query the usage data.
+ * @param cycles the time slots for the network cycle to be used to query the network usage.
+ * @return the builder
+ */
+ public Builder<T> setCycles(ArrayList<Long> cycles) {
+ mCycles = cycles;
+ return this;
+ }
+
public abstract T build();
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
index b8a143a376fd..c5f54bb0f0d9 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
@@ -46,6 +46,7 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.util.ReflectionHelpers;
import java.time.ZonedDateTime;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -99,6 +100,20 @@ public class NetworkCycleDataLoaderTest {
}
@Test
+ public void loadInBackground_hasCyclePeriod_shouldLoadDataForSpecificCycles() {
+ mLoader = spy(new NetworkCycleDataTestLoader(mContext));
+ doNothing().when(mLoader).loadDataForSpecificCycles();
+ final ArrayList<Long> cycles = new ArrayList<>();
+ cycles.add(67890L);
+ cycles.add(12345L);
+ ReflectionHelpers.setField(mLoader, "mCycles", cycles);
+
+ mLoader.loadInBackground();
+
+ verify(mLoader).loadDataForSpecificCycles();
+ }
+
+ @Test
public void loadPolicyData_shouldRecordUsageFromPolicyCycle() {
final int networkType = ConnectivityManager.TYPE_MOBILE;
final String subId = "TestSubscriber";
@@ -139,6 +154,27 @@ public class NetworkCycleDataLoaderTest {
verify(mLoader).recordUsage(fourWeeksAgo, now);
}
+ @Test
+ public void loadDataForSpecificCycles_shouldRecordUsageForSpecifiedTime() {
+ mLoader = spy(new NetworkCycleDataTestLoader(mContext));
+ final long now = System.currentTimeMillis();
+ final long tenDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 10);
+ final long twentyDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 20);
+ final long thirtyDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 30);
+ final ArrayList<Long> cycles = new ArrayList<>();
+ cycles.add(now);
+ cycles.add(tenDaysAgo);
+ cycles.add(twentyDaysAgo);
+ cycles.add(thirtyDaysAgo);
+ ReflectionHelpers.setField(mLoader, "mCycles", cycles);
+
+ mLoader.loadDataForSpecificCycles();
+
+ verify(mLoader).recordUsage(tenDaysAgo, now);
+ verify(mLoader).recordUsage(twentyDaysAgo, tenDaysAgo);
+ verify(mLoader).recordUsage(thirtyDaysAgo, twentyDaysAgo);
+ }
+
public class NetworkCycleDataTestLoader extends NetworkCycleDataLoader<List<NetworkCycleData>> {
private NetworkCycleDataTestLoader(Context context) {
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 078108d658ee..95981427b642 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -15,7 +15,6 @@
*/
package com.android.keyguard.clock;
-import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
@@ -26,18 +25,16 @@ import android.os.Looper;
import android.provider.Settings;
import android.view.LayoutInflater;
-import androidx.annotation.VisibleForTesting;
-
import com.android.keyguard.R;
-import com.android.systemui.dock.DockManager;
-import com.android.systemui.dock.DockManager.DockEventListener;
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.ExtensionController.Extension;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.function.Consumer;
+import java.util.function.Supplier;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -48,6 +45,7 @@ import javax.inject.Singleton;
@Singleton
public final class ClockManager {
+ private final LayoutInflater mLayoutInflater;
private final ContentResolver mContentResolver;
private final List<ClockInfo> mClockInfos = new ArrayList<>();
@@ -64,6 +62,7 @@ public final class ClockManager {
}
}
};
+
private final ExtensionController mExtensionController;
/**
* Used to select between plugin or default implementations of ClockPlugin interface.
@@ -73,35 +72,13 @@ public final class ClockManager {
* Consumer that accepts the a new ClockPlugin implementation when the Extension reloads.
*/
private final Consumer<ClockPlugin> mClockPluginConsumer = this::setClockPlugin;
- /**
- * Supplier of default ClockPlugin implementation.
- */
- private final DefaultClockSupplier mDefaultClockSupplier;
- /**
- * Observe changes to dock state to know when to switch the clock face.
- */
- private final DockEventListener mDockEventListener =
- new DockEventListener() {
- @Override
- public void onEvent(int event) {
- final boolean isDocked = (event == DockManager.STATE_DOCKED
- || event == DockManager.STATE_DOCKED_HIDE);
- mDefaultClockSupplier.setDocked(isDocked);
- if (mClockExtension != null) {
- mClockExtension.reload();
- }
- }
- };
- @Nullable
- private final DockManager mDockManager;
private final List<ClockChangedListener> mListeners = new ArrayList<>();
@Inject
- public ClockManager(Context context, ExtensionController extensionController,
- @Nullable DockManager dockManager) {
+ public ClockManager(Context context, ExtensionController extensionController) {
mExtensionController = extensionController;
- mDockManager = dockManager;
+ mLayoutInflater = LayoutInflater.from(context);
mContentResolver = context.getContentResolver();
Resources res = context.getResources();
@@ -133,9 +110,6 @@ public final class ClockManager {
.setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.type_thumbnail))
.setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.type_preview))
.build());
-
- mDefaultClockSupplier = new DefaultClockSupplier(new SettingsWrapper(mContentResolver),
- LayoutInflater.from(context));
}
/**
@@ -180,32 +154,41 @@ public final class ClockManager {
mContentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE),
false, mContentObserver);
- mContentResolver.registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.DOCKED_CLOCK_FACE),
- false, mContentObserver);
- if (mDockManager != null) {
- mDockManager.addListener(mDockEventListener);
- }
mClockExtension = mExtensionController.newExtension(ClockPlugin.class)
.withPlugin(ClockPlugin.class)
.withCallback(mClockPluginConsumer)
- .withDefault(mDefaultClockSupplier)
+ // Using withDefault even though this isn't the default as a workaround.
+ // ExtensionBuilder doesn't provide the ability to supply a ClockPlugin
+ // instance based off of the value of a setting. Since multiple "default"
+ // can be provided, using a supplier that changes the settings value.
+ // A null return will cause Extension#reload to look at the next "default"
+ // supplier.
+ .withDefault(
+ new SettingsGattedSupplier(
+ mContentResolver,
+ Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
+ BubbleClockController.class.getName(),
+ () -> BubbleClockController.build(mLayoutInflater)))
+ .withDefault(
+ new SettingsGattedSupplier(
+ mContentResolver,
+ Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
+ StretchAnalogClockController.class.getName(),
+ () -> StretchAnalogClockController.build(mLayoutInflater)))
+ .withDefault(
+ new SettingsGattedSupplier(
+ mContentResolver,
+ Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
+ TypeClockController.class.getName(),
+ () -> TypeClockController.build(mLayoutInflater)))
.build();
}
private void unregister() {
mContentResolver.unregisterContentObserver(mContentObserver);
- if (mDockManager != null) {
- mDockManager.removeListener(mDockEventListener);
- }
mClockExtension.destroy();
}
- @VisibleForTesting
- boolean isDocked() {
- return mDefaultClockSupplier.isDocked();
- }
-
/**
* Listener for events that should cause the custom clock face to change.
*/
@@ -217,4 +200,44 @@ public final class ClockManager {
*/
void onClockChanged(ClockPlugin clock);
}
+
+ /**
+ * Supplier that only gets an instance when a settings value matches expected value.
+ */
+ private static class SettingsGattedSupplier implements Supplier<ClockPlugin> {
+
+ private final ContentResolver mContentResolver;
+ private final String mKey;
+ private final String mValue;
+ private final Supplier<ClockPlugin> mSupplier;
+
+ /**
+ * Constructs a supplier that changes secure setting key against value.
+ *
+ * @param contentResolver Used to look up settings value.
+ * @param key Settings key.
+ * @param value If the setting matches this values that get supplies a ClockPlugin
+ * instance.
+ * @param supplier Supplier of ClockPlugin instance, only used if the setting
+ * matches value.
+ */
+ SettingsGattedSupplier(ContentResolver contentResolver, String key, String value,
+ Supplier<ClockPlugin> supplier) {
+ mContentResolver = contentResolver;
+ mKey = key;
+ mValue = value;
+ mSupplier = supplier;
+ }
+
+ /**
+ * Returns null if the settings value doesn't match the expected value.
+ *
+ * A null return causes Extension#reload to skip this supplier and move to the next.
+ */
+ @Override
+ public ClockPlugin get() {
+ final String currentValue = Settings.Secure.getString(mContentResolver, mKey);
+ return Objects.equals(currentValue, mValue) ? mSupplier.get() : null;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockSupplier.java b/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockSupplier.java
deleted file mode 100644
index 7fdd2357bc8e..000000000000
--- a/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockSupplier.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2019 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.keyguard.clock;
-
-import android.util.ArrayMap;
-import android.view.LayoutInflater;
-
-import com.android.systemui.plugins.ClockPlugin;
-
-import java.util.Map;
-import java.util.function.Supplier;
-
-/**
- * Supplier that only gets an instance when a settings value matches expected value.
- */
-public class DefaultClockSupplier implements Supplier<ClockPlugin> {
-
- private final SettingsWrapper mSettingsWrapper;
- /**
- * Map from expected value stored in settings to supplier of custom clock face.
- */
- private final Map<String, Supplier<ClockPlugin>> mClocks = new ArrayMap<>();
- /**
- * When docked, the DOCKED_CLOCK_FACE setting will be checked for the custom clock face
- * to show.
- */
- private boolean mIsDocked;
-
- /**
- * Constructs a supplier that changes secure setting key against value.
- *
- * @param settingsWrapper Wrapper around settings used to look up the custom clock face.
- * @param layoutInflater Provided to clocks as dependency to inflate clock views.
- */
- public DefaultClockSupplier(SettingsWrapper settingsWrapper, LayoutInflater layoutInflater) {
- mSettingsWrapper = settingsWrapper;
-
- mClocks.put(BubbleClockController.class.getName(),
- () -> BubbleClockController.build(layoutInflater));
- mClocks.put(StretchAnalogClockController.class.getName(),
- () -> StretchAnalogClockController.build(layoutInflater));
- mClocks.put(TypeClockController.class.getName(),
- () -> TypeClockController.build(layoutInflater));
- }
-
- /**
- * Sets the dock state.
- *
- * @param isDocked True when docked, false otherwise.
- */
- public void setDocked(boolean isDocked) {
- mIsDocked = isDocked;
- }
-
- boolean isDocked() {
- return mIsDocked;
- }
-
- /**
- * Get the custom clock face based on values in settings.
- *
- * @return Custom clock face, null if the settings value doesn't match a custom clock.
- */
- @Override
- public ClockPlugin get() {
- ClockPlugin plugin = null;
- if (mIsDocked) {
- final String name = mSettingsWrapper.getDockedClockFace();
- if (name != null) {
- Supplier<ClockPlugin> supplier = mClocks.get(name);
- if (supplier != null) {
- plugin = supplier.get();
- if (plugin != null) {
- return plugin;
- }
- }
- }
- }
- final String name = mSettingsWrapper.getLockScreenCustomClockFace();
- if (name != null) {
- Supplier<ClockPlugin> supplier = mClocks.get(name);
- if (supplier != null) {
- plugin = supplier.get();
- }
- }
- return plugin;
- }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/SettingsWrapper.java b/packages/SystemUI/src/com/android/keyguard/clock/SettingsWrapper.java
deleted file mode 100644
index 58e11553af9d..000000000000
--- a/packages/SystemUI/src/com/android/keyguard/clock/SettingsWrapper.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2019 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.keyguard.clock;
-
-import android.content.ContentResolver;
-import android.provider.Settings;
-
-/**
- * Wrapper around Settings used for testing.
- */
-public class SettingsWrapper {
-
- private static final String CUSTOM_CLOCK_FACE = Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE;
- private static final String DOCKED_CLOCK_FACE = Settings.Secure.DOCKED_CLOCK_FACE;
-
- private ContentResolver mContentResolver;
-
- public SettingsWrapper(ContentResolver contentResolver) {
- mContentResolver = contentResolver;
- }
-
- /**
- * Gets the value stored in settings for the custom clock face.
- */
- public String getLockScreenCustomClockFace() {
- return Settings.Secure.getString(mContentResolver, CUSTOM_CLOCK_FACE);
- }
-
- /**
- * Gets the value stored in settings for the clock face to use when docked.
- */
- public String getDockedClockFace() {
- return Settings.Secure.getString(mContentResolver, DOCKED_CLOCK_FACE);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index d27a90332ac5..755d6fcffb43 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -31,7 +31,6 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.classifier.FalsingManager;
-import com.android.systemui.dock.DockManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -229,16 +228,6 @@ public class SystemUIFactory {
return SysUiServiceProvider.getComponent(context, StatusBar.class);
}
- /**
- * Provides DockManager.
- */
- @Singleton
- @Provides
- @Nullable
- public DockManager providesDockManager(Context context) {
- return SysUiServiceProvider.getComponent(context, DockManager.class);
- }
-
@Module
protected static class ContextHolder {
private Context mContext;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
deleted file mode 100644
index f813ac693d42..000000000000
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2019 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.keyguard.clock;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.LeakCheck;
-import android.testing.TestableLooper.RunWithLooper;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dock.DockManager;
-import com.android.systemui.dock.DockManagerFake;
-import com.android.systemui.utils.leaks.FakeExtensionController;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-public final class ClockManagerTest extends SysuiTestCase {
-
- private ClockManager mClockManager;
- private LeakCheck mLeakCheck;
- private FakeExtensionController mFakeExtensionController;
- private DockManagerFake mFakeDockManager;
- @Mock ClockManager.ClockChangedListener mMockListener;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mLeakCheck = new LeakCheck();
- mFakeExtensionController = new FakeExtensionController(mLeakCheck);
- mFakeDockManager = new DockManagerFake();
- mClockManager = new ClockManager(getContext(), mFakeExtensionController,
- mFakeDockManager);
- mClockManager.addOnClockChangedListener(mMockListener);
- }
-
- @After
- public void tearDown() {
- mClockManager.removeOnClockChangedListener(mMockListener);
- }
-
- @Test
- public void dockEvent() {
- mFakeDockManager.setDockEvent(DockManager.STATE_DOCKED);
- assertThat(mClockManager.isDocked()).isTrue();
- }
-
- @Test
- public void undockEvent() {
- mFakeDockManager.setDockEvent(DockManager.STATE_NONE);
- assertThat(mClockManager.isDocked()).isFalse();
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/DefaultClockSupplierTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/DefaultClockSupplierTest.java
deleted file mode 100644
index 1a3b198ac0d6..000000000000
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/DefaultClockSupplierTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2019 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.keyguard.clock;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.when;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.LayoutInflater;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.ClockPlugin;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-public final class DefaultClockSupplierTest extends SysuiTestCase {
-
- private static final String BUBBLE_CLOCK = BubbleClockController.class.getName();
- private static final Class<?> BUBBLE_CLOCK_CLASS = BubbleClockController.class;
-
- private DefaultClockSupplier mDefaultClockSupplier;
- @Mock SettingsWrapper mMockSettingsWrapper;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mDefaultClockSupplier = new DefaultClockSupplier(mMockSettingsWrapper,
- LayoutInflater.from(getContext()));
- }
-
- @Test
- public void get_default() {
- // GIVEN that settings doesn't contain any values
- when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn(null);
- when(mMockSettingsWrapper.getDockedClockFace()).thenReturn(null);
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the result is null, indicated the default clock face should be used.
- assertThat(plugin).isNull();
- }
-
- @Test
- public void get_customClock() {
- // GIVEN that settings is set to the bubble clock face
- when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn(BUBBLE_CLOCK);
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the plugin is the bubble clock face.
- assertThat(plugin).isInstanceOf(BUBBLE_CLOCK_CLASS);
- }
-
- @Test
- public void get_badSettingsValue() {
- // GIVEN that settings contains a value that doesn't correspond to a
- // custom clock face.
- when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn("bad value");
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the result is null.
- assertThat(plugin).isNull();
- }
-
- @Test
- public void get_dockedDefault() {
- // GIVEN docked
- mDefaultClockSupplier.setDocked(true);
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the result is null, indicating the default clock face.
- assertThat(plugin).isNull();
- }
-
- @Test
- public void get_dockedCustomClock() {
- // GIVEN docked and settings is set to the bubble clock face
- mDefaultClockSupplier.setDocked(true);
- when(mMockSettingsWrapper.getDockedClockFace()).thenReturn(BUBBLE_CLOCK);
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the plugin is the bubble clock face.
- assertThat(plugin).isInstanceOf(BUBBLE_CLOCK_CLASS);
- }
-
- @Test
- public void get_badDockedSettingsValue() {
- // GIVEN docked and settings contains a value that doesn't correspond to
- // an available clock face.
- mDefaultClockSupplier.setDocked(true);
- when(mMockSettingsWrapper.getDockedClockFace()).thenReturn("bad value");
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the result is null.
- assertThat(plugin).isNull();
- }
-
- @Test
- public void get_badDockedSettingsFallback() {
- // GIVEN docked and settings contains a value that doesn't correspond to
- // an available clock face, but locked screen settings is set to bubble
- // clock.
- mDefaultClockSupplier.setDocked(true);
- when(mMockSettingsWrapper.getDockedClockFace()).thenReturn("bad value");
- when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn(BUBBLE_CLOCK);
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the plugin is the bubble clock face.
- assertThat(plugin).isInstanceOf(BUBBLE_CLOCK_CLASS);
- }
-}
diff --git a/services/core/java/com/android/server/ExtconUEventObserver.java b/services/core/java/com/android/server/ExtconUEventObserver.java
index b3084f50071f..ebd4c5584fe1 100644
--- a/services/core/java/com/android/server/ExtconUEventObserver.java
+++ b/services/core/java/com/android/server/ExtconUEventObserver.java
@@ -22,8 +22,11 @@ import android.util.Slog;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.regex.Pattern;
/**
* A specialized UEventObserver that receives UEvents from the kernel for devices in the {@code
@@ -40,13 +43,14 @@ import java.util.Map;
* time in that process. Once started the UEvent thread will not stop (although it can stop
* notifying UEventObserver's via stopObserving()).
*
- * <p>
- *
* @hide
*/
public abstract class ExtconUEventObserver extends UEventObserver {
private static final String TAG = "ExtconUEventObserver";
private static final boolean LOG = false;
+ private static final String SELINUX_POLICIES_NEED_TO_BE_CHANGED =
+ "This probably mean the selinux policies need to be changed.";
+
private final Map<String, ExtconInfo> mExtconInfos = new ArrayMap<>();
@Override
@@ -70,15 +74,47 @@ public abstract class ExtconUEventObserver extends UEventObserver {
/** Starts observing {@link ExtconInfo#getDevicePath()}. */
public void startObserving(ExtconInfo extconInfo) {
- mExtconInfos.put(extconInfo.getDevicePath(), extconInfo);
- if (LOG) Slog.v(TAG, "Observing " + extconInfo.getDevicePath());
- startObserving("DEVPATH=" + extconInfo.getDevicePath());
+ String devicePath = extconInfo.getDevicePath();
+ if (devicePath == null) {
+ Slog.wtf(TAG, "Unable to start observing " + extconInfo.getName()
+ + " because the device path is null. " + SELINUX_POLICIES_NEED_TO_BE_CHANGED);
+ } else {
+ mExtconInfos.put(devicePath, extconInfo);
+ if (LOG) Slog.v(TAG, "Observing " + devicePath);
+ startObserving("DEVPATH=" + devicePath);
+ }
}
/** An External Connection to watch. */
public static final class ExtconInfo {
private static final String TAG = "ExtconInfo";
+ /** Returns a new list of all external connections whose name matches {@code regex}. */
+ public static List<ExtconInfo> getExtconInfos(@Nullable String regex) {
+ Pattern p = regex == null ? null : Pattern.compile(regex);
+ File file = new File("/sys/class/extcon");
+ File[] files = file.listFiles();
+ if (files == null) {
+ Slog.wtf(TAG, file + " exists " + file.exists() + " isDir " + file.isDirectory()
+ + " but listFiles returns null. "
+ + SELINUX_POLICIES_NEED_TO_BE_CHANGED);
+ return new ArrayList<>(0); // Always return a new list.
+ } else {
+ ArrayList list = new ArrayList(files.length);
+ for (File f : files) {
+ String name = f.getName();
+ if (p == null || p.matcher(name).matches()) {
+ ExtconInfo uei = new ExtconInfo(name);
+ list.add(uei);
+ if (LOG) Slog.d(TAG, name + " matches " + regex);
+ } else {
+ if (LOG) Slog.d(TAG, name + " does not match " + regex);
+ }
+ }
+ return list;
+ }
+ }
+
private final String mName;
public ExtconInfo(String name) {
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index 3939bee52aa2..9bbc3158757c 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -23,6 +23,7 @@ import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.UEventObserver;
+import android.util.Pair;
import android.util.Slog;
import android.media.AudioManager;
import android.util.Log;
@@ -31,6 +32,7 @@ import android.view.InputDevice;
import com.android.internal.R;
import com.android.server.input.InputManagerService;
import com.android.server.input.InputManagerService.WiredAccessoryCallbacks;
+
import static com.android.server.input.InputManagerService.SW_HEADPHONE_INSERT;
import static com.android.server.input.InputManagerService.SW_MICROPHONE_INSERT;
import static com.android.server.input.InputManagerService.SW_LINEOUT_INSERT;
@@ -41,6 +43,7 @@ import static com.android.server.input.InputManagerService.SW_LINEOUT_INSERT_BIT
import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -52,7 +55,7 @@ import java.util.Locale;
*/
final class WiredAccessoryManager implements WiredAccessoryCallbacks {
private static final String TAG = WiredAccessoryManager.class.getSimpleName();
- private static final boolean LOG = true;
+ private static final boolean LOG = false;
private static final int BIT_HEADSET = (1 << 0);
private static final int BIT_HEADSET_NO_MIC = (1 << 1);
@@ -60,9 +63,9 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
private static final int BIT_USB_HEADSET_DGTL = (1 << 3);
private static final int BIT_HDMI_AUDIO = (1 << 4);
private static final int BIT_LINEOUT = (1 << 5);
- private static final int SUPPORTED_HEADSETS = (BIT_HEADSET|BIT_HEADSET_NO_MIC|
- BIT_USB_HEADSET_ANLG|BIT_USB_HEADSET_DGTL|
- BIT_HDMI_AUDIO|BIT_LINEOUT);
+ private static final int SUPPORTED_HEADSETS = (BIT_HEADSET | BIT_HEADSET_NO_MIC |
+ BIT_USB_HEADSET_ANLG | BIT_USB_HEADSET_DGTL |
+ BIT_HDMI_AUDIO | BIT_LINEOUT);
private static final String NAME_H2W = "h2w";
private static final String NAME_USB_AUDIO = "usb_audio";
@@ -82,30 +85,34 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
private int mSwitchValues;
private final WiredAccessoryObserver mObserver;
+ private final WiredAccessoryExtconObserver mExtconObserver;
private final InputManagerService mInputManager;
private final boolean mUseDevInputEventForAudioJack;
public WiredAccessoryManager(Context context, InputManagerService inputManager) {
- PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryManager");
mWakeLock.setReferenceCounted(false);
- mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mInputManager = inputManager;
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
+ mExtconObserver = new WiredAccessoryExtconObserver();
mObserver = new WiredAccessoryObserver();
}
private void onSystemReady() {
if (mUseDevInputEventForAudioJack) {
int switchValues = 0;
- if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_HEADPHONE_INSERT) == 1) {
+ if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_HEADPHONE_INSERT)
+ == 1) {
switchValues |= SW_HEADPHONE_INSERT_BIT;
}
- if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_MICROPHONE_INSERT) == 1) {
+ if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_MICROPHONE_INSERT)
+ == 1) {
switchValues |= SW_MICROPHONE_INSERT_BIT;
}
if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_LINEOUT_INSERT) == 1) {
@@ -115,20 +122,31 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT);
}
- mObserver.init();
+
+ if (ExtconUEventObserver.extconExists()) {
+ if (mUseDevInputEventForAudioJack) {
+ Log.w(TAG, "Both input event and extcon are used for audio jack,"
+ + " please just choose one.");
+ }
+ mExtconObserver.init();
+ } else {
+ mObserver.init();
+ }
}
@Override
public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask) {
- if (LOG) Slog.v(TAG, "notifyWiredAccessoryChanged: when=" + whenNanos
- + " bits=" + switchCodeToString(switchValues, switchMask)
- + " mask=" + Integer.toHexString(switchMask));
+ if (LOG) {
+ Slog.v(TAG, "notifyWiredAccessoryChanged: when=" + whenNanos
+ + " bits=" + switchCodeToString(switchValues, switchMask)
+ + " mask=" + Integer.toHexString(switchMask));
+ }
synchronized (mLock) {
int headset;
mSwitchValues = (mSwitchValues & ~switchMask) | switchValues;
switch (mSwitchValues &
- (SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT)) {
+ (SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT)) {
case 0:
headset = 0;
break;
@@ -155,7 +173,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
}
updateLocked(NAME_H2W,
- (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset);
+ (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset);
}
}
@@ -175,7 +193,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
* results in support for the last one plugged in. Similarly, unplugging either is seen as
* unplugging all.
*
- * @param newName One of the NAME_xxx variables defined above.
+ * @param newName One of the NAME_xxx variables defined above.
* @param newState 0 or one of the BIT_xxx variables defined above.
*/
private void updateLocked(String newName, int newState) {
@@ -186,10 +204,12 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT);
boolean h2wStateChange = true;
boolean usbStateChange = true;
- if (LOG) Slog.v(TAG, "newName=" + newName
- + " newState=" + newState
- + " headsetState=" + headsetState
- + " prev headsetState=" + mHeadsetState);
+ if (LOG) {
+ Slog.v(TAG, "newName=" + newName
+ + " newState=" + newState
+ + " headsetState=" + headsetState
+ + " prev headsetState=" + mHeadsetState);
+ }
if (mHeadsetState == headsetState) {
Log.e(TAG, "No state change.");
@@ -229,7 +249,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_NEW_DEVICE_STATE:
- setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);
+ setDevicesState(msg.arg1, msg.arg2, (String) msg.obj);
mWakeLock.release();
break;
case MSG_SYSTEM_READY:
@@ -269,9 +289,9 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
if (headset == BIT_HEADSET) {
outDevice = AudioManager.DEVICE_OUT_WIRED_HEADSET;
inDevice = AudioManager.DEVICE_IN_WIRED_HEADSET;
- } else if (headset == BIT_HEADSET_NO_MIC){
+ } else if (headset == BIT_HEADSET_NO_MIC) {
outDevice = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;
- } else if (headset == BIT_LINEOUT){
+ } else if (headset == BIT_LINEOUT) {
outDevice = AudioManager.DEVICE_OUT_LINE;
} else if (headset == BIT_USB_HEADSET_ANLG) {
outDevice = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;
@@ -280,7 +300,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
} else if (headset == BIT_HDMI_AUDIO) {
outDevice = AudioManager.DEVICE_OUT_HDMI;
} else {
- Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
+ Slog.e(TAG, "setDeviceState() invalid headset type: " + headset);
return;
}
@@ -290,10 +310,10 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
}
if (outDevice != 0) {
- mAudioManager.setWiredDeviceConnectionState(outDevice, state, "", headsetName);
+ mAudioManager.setWiredDeviceConnectionState(outDevice, state, "", headsetName);
}
if (inDevice != 0) {
- mAudioManager.setWiredDeviceConnectionState(inDevice, state, "", headsetName);
+ mAudioManager.setWiredDeviceConnectionState(inDevice, state, "", headsetName);
}
}
}
@@ -340,7 +360,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
" not found while attempting to determine initial switch state");
} catch (Exception e) {
Slog.e(TAG, "Error while attempting to determine initial switch state for "
- + uei.getDevName() , e);
+ + uei.getDevName(), e);
}
}
}
@@ -350,7 +370,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
// observe three UEVENTs
for (int i = 0; i < mUEventInfo.size(); ++i) {
UEventInfo uei = mUEventInfo.get(i);
- startObserving("DEVPATH="+uei.getDevPath());
+ startObserving("DEVPATH=" + uei.getDevPath());
}
}
@@ -438,7 +458,9 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
mStateNbits = stateNbits;
}
- public String getDevName() { return mDevName; }
+ public String getDevName() {
+ return mDevName;
+ }
public String getDevPath() {
return String.format(Locale.US, "/devices/virtual/switch/%s", mDevName);
@@ -456,11 +478,84 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
public int computeNewHeadsetState(int headsetState, int switchState) {
int preserveMask = ~(mState1Bits | mState2Bits | mStateNbits);
int setBits = ((switchState == 1) ? mState1Bits :
- ((switchState == 2) ? mState2Bits :
- ((switchState == mStateNbits) ? mStateNbits : 0)));
+ ((switchState == 2) ? mState2Bits :
+ ((switchState == mStateNbits) ? mStateNbits : 0)));
return ((headsetState & preserveMask) | setBits);
}
}
}
+
+ private class WiredAccessoryExtconObserver extends ExtconStateObserver<Pair<Integer, Integer>> {
+ private final List<ExtconInfo> mExtconInfos;
+
+ WiredAccessoryExtconObserver() {
+ mExtconInfos = ExtconInfo.getExtconInfos(".*audio.*");
+
+ }
+
+ private void init() {
+ for (ExtconInfo extconInfo : mExtconInfos) {
+ Pair<Integer, Integer> state = null;
+ try {
+ state = parseStateFromFile(extconInfo);
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, extconInfo.getStatePath()
+ + " not found while attempting to determine initial state", e);
+ } catch (IOException e) {
+ Slog.e(
+ TAG,
+ "Error reading " + extconInfo.getStatePath()
+ + " while attempting to determine initial state",
+ e);
+ }
+ if (state != null) {
+ updateState(extconInfo, extconInfo.getName(), state);
+ }
+ if (LOG) Slog.d(TAG, "observing " + extconInfo.getName());
+ startObserving(extconInfo);
+ }
+
+ }
+
+ @Override
+ public Pair<Integer, Integer> parseState(ExtconInfo extconInfo, String status) {
+ if (LOG) Slog.v(TAG, "status " + status);
+ int []maskAndState = {0,0};
+ // extcon event state changes from kernel4.9
+ // new state will be like STATE=MICROPHONE=1\nHEADPHONE=0
+ updateBit(maskAndState, BIT_HEADSET_NO_MIC, status, "HEADPHONE") ;
+ updateBit(maskAndState, BIT_HEADSET, status,"MICROPHONE") ;
+ updateBit(maskAndState, BIT_HDMI_AUDIO, status,"HDMI") ;
+ updateBit(maskAndState, BIT_LINEOUT, status,"LINE-OUT") ;
+ if (LOG) Slog.v(TAG, "mask " + maskAndState[0] + " state " + maskAndState[1]);
+ return Pair.create(maskAndState[0],maskAndState[1]);
+ }
+
+ @Override
+ public void updateState(ExtconInfo extconInfo, String name,
+ Pair<Integer, Integer> maskAndState) {
+ synchronized (mLock) {
+ int mask = maskAndState.first;
+ int state = maskAndState.second;
+ updateLocked(name, mHeadsetState | (mask & state) & ~(mask & ~state));
+ return;
+ }
+ }
+ }
+
+ /**
+ * Updates the mask bit at {@code position} to 1 and the state bit at {@code position} to true
+ * if {@code name=1} or false if {}@code name=0} is contained in {@code state}.
+ */
+ private static void updateBit(int[] maskAndState, int position, String state, String name) {
+ maskAndState[0] |= position;
+ if (state.contains(name + "=1")) {
+ maskAndState[0] |= position;
+ maskAndState[1] |= position;
+ } else if (state.contains(name + "=0")) {
+ maskAndState[0] |= position;
+ maskAndState[1] &= ~position;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 5e7ea05f799c..28393a209111 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -1805,9 +1805,10 @@ public class InputManagerService extends IInputManager.Stub
}
// Native callback.
- private int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+ private int interceptMotionBeforeQueueingNonInteractive(int displayId,
+ long whenNanos, int policyFlags) {
return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive(
- whenNanos, policyFlags);
+ displayId, whenNanos, policyFlags);
}
// Native callback.
@@ -2021,7 +2022,13 @@ public class InputManagerService extends IInputManager.Stub
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
- public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
+ /**
+ * Provides an opportunity for the window manager policy to intercept early motion event
+ * processing when the device is in a non-interactive state since these events are normally
+ * dropped.
+ */
+ int interceptMotionBeforeQueueingNonInteractive(int displayId, long whenNanos,
+ int policyFlags);
public long interceptKeyBeforeDispatching(IBinder token,
KeyEvent event, int policyFlags);
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 2f0b388b9a7d..3abacc2c9c10 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -976,7 +976,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
- if (mProviderRequest.reportLocation && !mDisableGps && isEnabled()) {
+ if (mProviderRequest.reportLocation && isEnabled()) {
// update client uids
updateClientUids(mWorkSource);
diff --git a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
index 5c7317892f3f..62d9b20b636d 100644
--- a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
@@ -284,13 +284,16 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
* Tells the system UI that volume has changed on an active remote session.
*/
public void notifyRemoteVolumeChanged(int flags, MediaSessionRecord session) {
- if (mRvc == null || !session.isActive()) {
- return;
- }
- try {
- mRvc.remoteVolumeChanged(session.getSessionToken(), flags);
- } catch (Exception e) {
- Log.wtf(TAG, "Error sending volume change to system UI.", e);
+ synchronized (mLock) {
+ if (mRvc == null || !session.isActive()) {
+ return;
+ }
+ try {
+ mRvc.remoteVolumeChanged(session.getSessionToken(), flags);
+ } catch (Exception e) {
+ Log.w(TAG, "Error sending volume change to system UI.", e);
+ mRvc = null;
+ }
}
}
@@ -563,7 +566,7 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
String callerPackageName, SessionCallbackLink cb, String tag) {
FullUserRecord user = getFullUserRecordLocked(userId);
if (user == null) {
- Log.wtf(TAG, "Request from invalid user: " + userId);
+ Log.w(TAG, "Request from invalid user: " + userId + ", pkg=" + callerPackageName);
throw new RuntimeException("Session request from invalid user.");
}
@@ -643,7 +646,8 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
mRvc.updateRemoteController(record == null ? null : record.getSessionToken());
} catch (RemoteException e) {
- Log.wtf(TAG, "Error sending default remote volume to sys ui.", e);
+ Log.w(TAG, "Error sending default remote volume to sys ui.", e);
+ mRvc = null;
}
}
}
@@ -1661,7 +1665,9 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
final long token = Binder.clearCallingIdentity();
try {
enforceSystemUiPermission("listen for volume changes", pid, uid);
- mRvc = rvc;
+ synchronized (mLock) {
+ mRvc = rvc;
+ }
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 8c00380b82b1..400443a16fab 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -123,6 +123,7 @@ import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppDetailsActivity;
import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.ResourcesManager;
import android.app.admin.IDevicePolicyManager;
@@ -1044,12 +1045,17 @@ public class PackageManagerService extends IPackageManager.Stub
verificationIntent.setComponent(mIntentFilterVerifierComponent);
verificationIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ final long whitelistTimeout = getVerificationTimeout();
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setTemporaryAppWhitelistDuration(whitelistTimeout);
+
DeviceIdleController.LocalService idleController = getDeviceIdleController();
idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
- mIntentFilterVerifierComponent.getPackageName(), getVerificationTimeout(),
+ mIntentFilterVerifierComponent.getPackageName(), whitelistTimeout,
UserHandle.USER_SYSTEM, true, "intent filter verifier");
- mContext.sendBroadcastAsUser(verificationIntent, UserHandle.SYSTEM);
+ mContext.sendBroadcastAsUser(verificationIntent, UserHandle.SYSTEM,
+ null, options.toBundle());
if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
"Sending IntentFilter verification broadcast");
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b00193f5453f..2e3e3e430839 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -22,7 +22,6 @@ import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.AppOpsManager.OP_TOAST_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.Context.CONTEXT_RESTRICTED;
-import static android.content.Context.DISPLAY_SERVICE;
import static android.content.Context.WINDOW_SERVICE;
import static android.content.pm.PackageManager.FEATURE_HDMI_CEC;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
@@ -36,6 +35,7 @@ import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.STATE_OFF;
+import static android.view.KeyEvent.KEYCODE_UNKNOWN;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
@@ -84,10 +84,8 @@ import static android.view.WindowManagerGlobal.ADD_OKAY;
import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
-import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs
- .CAMERA_LENS_COVER_ABSENT;
-import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs
- .CAMERA_LENS_UNCOVERED;
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_DELEGATE;
@@ -371,6 +369,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
IStatusBarService mStatusBarService;
StatusBarManagerInternal mStatusBarManagerInternal;
AudioManagerInternal mAudioManagerInternal;
+ DisplayManager mDisplayManager;
boolean mPreloadedRecentApps;
final Object mServiceAquireLock = new Object();
Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
@@ -1717,7 +1716,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
- mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+ mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
+ mDisplayManager = mContext.getSystemService(DisplayManager.class);
mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);
mHasFeatureHdmiCec = mContext.getPackageManager().hasSystemFeature(FEATURE_HDMI_CEC);
@@ -2508,8 +2508,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return context;
}
- final DisplayManager dm = (DisplayManager) context.getSystemService(DISPLAY_SERVICE);
- final Display targetDisplay = dm.getDisplay(displayId);
+ final Display targetDisplay = mDisplayManager.getDisplay(displayId);
if (targetDisplay == null) {
// Failed to obtain the non-default display where splash screen should be shown,
// lets not show at all.
@@ -3655,7 +3654,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Reset the pending key
mPendingWakeKey = PENDING_KEY_NULL;
}
- } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
+ } else if (!interactive && shouldDispatchInputWhenNonInteractive(displayId, keyCode)) {
// If we're currently dozing with the screen on and the keyguard showing, pass the key
// to the application but preserve its wake key status to make sure we still move
// from dozing to fully interactive if we would normally go from off to fully
@@ -4126,7 +4125,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// TODO(b/117479243): handle it in InputPolicy
/** {@inheritDoc} */
@Override
- public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+ public int interceptMotionBeforeQueueingNonInteractive(int displayId, long whenNanos,
+ int policyFlags) {
if ((policyFlags & FLAG_WAKE) != 0) {
if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
PowerManager.WAKE_REASON_WAKE_MOTION, "android.policy:MOTION")) {
@@ -4134,7 +4134,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- if (shouldDispatchInputWhenNonInteractive(null)) {
+ if (shouldDispatchInputWhenNonInteractive(displayId, KEYCODE_UNKNOWN)) {
return ACTION_PASS_TO_USER;
}
@@ -4149,9 +4149,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return 0;
}
- private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
- final boolean displayOff = (mDefaultDisplay == null
- || mDefaultDisplay.getState() == STATE_OFF);
+ private boolean shouldDispatchInputWhenNonInteractive(int displayId, int keyCode) {
+ // Apply the default display policy to unknown displays as well.
+ final boolean isDefaultDisplay = displayId == DEFAULT_DISPLAY
+ || displayId == INVALID_DISPLAY;
+ final Display display = isDefaultDisplay
+ ? mDefaultDisplay
+ : mDisplayManager.getDisplay(displayId);
+ final boolean displayOff = (display == null
+ || display.getState() == STATE_OFF);
if (displayOff && !mHasFeatureWatch) {
return false;
@@ -4163,25 +4169,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
// Watches handle BACK specially
- if (mHasFeatureWatch
- && event != null
- && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
- || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
+ if (mHasFeatureWatch && (keyCode == KeyEvent.KEYCODE_BACK
+ || keyCode == KeyEvent.KEYCODE_STEM_PRIMARY)) {
return false;
}
- // Send events to a dozing dream even if the screen is off since the dream
- // is in control of the state of the screen.
- IDreamManager dreamManager = getDreamManager();
+ // TODO(b/123372519): Refine when dream can support multi display.
+ if (isDefaultDisplay) {
+ // Send events to a dozing dream even if the screen is off since the dream
+ // is in control of the state of the screen.
+ IDreamManager dreamManager = getDreamManager();
- try {
- if (dreamManager != null && dreamManager.isDreaming()) {
- return true;
+ try {
+ if (dreamManager != null && dreamManager.isDreaming()) {
+ return true;
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "RemoteException when checking if dreaming", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "RemoteException when checking if dreaming", e);
}
-
// Otherwise, consume events since the user can't see what is being
// interacted with.
return false;
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index d1bd102f11dc..870d61b2ab90 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -1003,11 +1003,13 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
* affect the power state of the device, for example, waking on motions.
* Generally, it's best to keep as little as possible in the queue thread
* because it's the most fragile.
+ * @param displayId The display ID of the motion event.
* @param policyFlags The policy flags associated with the motion.
*
* @return Actions flags: may be {@link #ACTION_PASS_TO_USER}.
*/
- public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
+ int interceptMotionBeforeQueueingNonInteractive(int displayId, long whenNanos,
+ int policyFlags);
/**
* Called from the input dispatcher thread before a key is dispatched to a window.
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 0aa6051d67ff..f3393e2f29da 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -167,6 +167,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
public static final int CODE_DATA_BROADCAST = 1;
public static final int CODE_SUBSCRIBER_BROADCAST = 1;
+ public static final int CODE_ACTIVE_CONFIGS_BROADCAST = 1;
/**
* The last report time is provided with each intent registered to
* StatsManager#setFetchReportsOperation. This allows easy de-duping in the receiver if
@@ -356,6 +357,22 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
@Override
+ public void sendActiveConfigsChangedBroadcast(IBinder intentSenderBinder, long[] configIds) {
+ enforceCallingPermission();
+ IntentSender intentSender = new IntentSender(intentSenderBinder);
+ Intent intent = new Intent();
+ intent.putExtra(StatsManager.EXTRA_STATS_ACTIVE_CONFIG_KEYS, configIds);
+ try {
+ intentSender.sendIntent(mContext, CODE_ACTIVE_CONFIGS_BROADCAST, intent, null, null);
+ if (DEBUG) {
+ Slog.d(TAG, "Sent broadcast with config ids " + Arrays.toString(configIds));
+ }
+ } catch (IntentSender.SendIntentException e) {
+ Slog.w(TAG, "Unable to send active configs changed broadcast using IntentSender");
+ }
+ }
+
+ @Override
public void sendSubscriberBroadcast(IBinder intentSenderBinder, long configUid, long configKey,
long subscriptionId, long subscriptionRuleId, String[] cookies,
StatsDimensionsValue dimensionsValue) {
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index f9c9d33c561a..f46835eb51fc 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -163,15 +163,12 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
}
- /**
- * Provides an opportunity for the window manager policy to intercept early motion event
- * processing when the device is in a non-interactive state since these events are normally
- * dropped.
- */
+ /** {@inheritDoc} */
@Override
- public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+ public int interceptMotionBeforeQueueingNonInteractive(int displayId, long whenNanos,
+ int policyFlags) {
return mService.mPolicy.interceptMotionBeforeQueueingNonInteractive(
- whenNanos, policyFlags);
+ displayId, whenNanos, policyFlags);
}
/**
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index fb5b1d85a4a2..5c91d9e6fff2 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -300,7 +300,7 @@ class RootActivityContainer extends ConfigurationContainer
* corresponding record in display manager.
*/
// TODO: Look into consolidating with getActivityDisplay()
- ActivityDisplay getActivityDisplayOrCreate(int displayId) {
+ @Nullable ActivityDisplay getActivityDisplayOrCreate(int displayId) {
ActivityDisplay activityDisplay = getActivityDisplay(displayId);
if (activityDisplay != null) {
return activityDisplay;
@@ -1317,6 +1317,9 @@ class RootActivityContainer extends ConfigurationContainer
if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
synchronized (mService.mGlobalLock) {
final ActivityDisplay display = getActivityDisplayOrCreate(displayId);
+ if (display == null) {
+ return;
+ }
// Do not start home before booting, or it may accidentally finish booting before it
// starts. Instead, we expect home activities to be launched when the system is ready
// (ActivityManagerService#systemReady).
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index c18e98bab9c4..57377c633c9a 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -249,7 +249,8 @@ public:
virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags);
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig);
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
- virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
+ virtual void interceptMotionBeforeQueueing(const int32_t displayId, nsecs_t when,
+ uint32_t& policyFlags);
virtual nsecs_t interceptKeyBeforeDispatching(
const sp<IBinder>& token,
const KeyEvent* keyEvent, uint32_t policyFlags);
@@ -1066,7 +1067,8 @@ void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
}
}
-void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
+void NativeInputManager::interceptMotionBeforeQueueing(const int32_t displayId, nsecs_t when,
+ uint32_t& policyFlags) {
ATRACE_CALL();
// Policy:
// - Ignore untrusted events and pass them along.
@@ -1084,7 +1086,7 @@ void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& p
JNIEnv* env = jniEnv();
jint wmActions = env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive,
- when, policyFlags);
+ displayId, when, policyFlags);
if (checkAndClearExceptionFromCallback(env,
"interceptMotionBeforeQueueingNonInteractive")) {
wmActions = 0;
@@ -1794,7 +1796,7 @@ int register_android_server_InputManager(JNIEnv* env) {
"interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");
GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive, clazz,
- "interceptMotionBeforeQueueingNonInteractive", "(JI)I");
+ "interceptMotionBeforeQueueingNonInteractive", "(IJI)I");
GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
"interceptKeyBeforeDispatching",
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index bfb9193551f2..849772a4a26d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -156,7 +156,8 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
}
@Override
- public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+ public int interceptMotionBeforeQueueingNonInteractive(int displayId, long whenNanos,
+ int policyFlags) {
return 0;
}
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index 6b1b84cd3458..856f08107fd7 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -30,6 +30,7 @@ public final class CellIdentityNr extends CellIdentity {
private final int mNrArfcn;
private final int mPci;
private final int mTac;
+ private final long mNci;
/**
*
@@ -44,11 +45,12 @@ public final class CellIdentityNr extends CellIdentity {
* @hide
*/
public CellIdentityNr(int pci, int tac, int nrArfcn, String mccStr, String mncStr,
- String alphal, String alphas) {
+ long nci, String alphal, String alphas) {
super(TAG, CellInfo.TYPE_NR, mccStr, mncStr, alphal, alphas);
mPci = pci;
mTac = tac;
mNrArfcn = nrArfcn;
+ mNci = nci;
}
/**
@@ -62,7 +64,7 @@ public final class CellIdentityNr extends CellIdentity {
@Override
public int hashCode() {
- return Objects.hash(super.hashCode(), mPci, mTac, mNrArfcn);
+ return Objects.hash(super.hashCode(), mPci, mTac, mNrArfcn, mNci);
}
@Override
@@ -72,7 +74,17 @@ public final class CellIdentityNr extends CellIdentity {
}
CellIdentityNr o = (CellIdentityNr) other;
- return super.equals(o) && mPci == o.mPci && mTac == o.mTac && mNrArfcn == o.mNrArfcn;
+ return super.equals(o) && mPci == o.mPci && mTac == o.mTac && mNrArfcn == o.mNrArfcn
+ && mNci == o.mNci;
+ }
+
+ /**
+ * Get the NR Cell Identity.
+ *
+ * @return The NR Cell Identity in range [0, 68719476735] or Long.MAX_VALUE if unknown.
+ */
+ public long getNci() {
+ return mNci;
}
/**
@@ -122,6 +134,7 @@ public final class CellIdentityNr extends CellIdentity {
.append(" mNrArfcn = ").append(mNrArfcn)
.append(" mMcc = ").append(mMccStr)
.append(" mMnc = ").append(mMncStr)
+ .append(" mNci = ").append(mNci)
.append(" mAlphaLong = ").append(mAlphaLong)
.append(" mAlphaShort = ").append(mAlphaShort)
.append(" }")
@@ -134,6 +147,7 @@ public final class CellIdentityNr extends CellIdentity {
dest.writeInt(mPci);
dest.writeInt(mTac);
dest.writeInt(mNrArfcn);
+ dest.writeLong(mNci);
}
/** Construct from Parcel, type has already been processed */
@@ -142,6 +156,7 @@ public final class CellIdentityNr extends CellIdentity {
mPci = in.readInt();
mTac = in.readInt();
mNrArfcn = in.readInt();
+ mNci = in.readLong();
}
/** Implement the Parcelable interface */
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index ceb76b57ae0c..c37b492a9cf1 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -27,6 +27,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Objects;
+import java.util.stream.Collectors;
/**
* Description of a mobile network registration state
@@ -360,7 +361,34 @@ public class NetworkRegistrationState implements Parcelable {
return 0;
}
- private static String regStateToString(int regState) {
+ /**
+ * Convert service type to string
+ *
+ * @hide
+ *
+ * @param serviceType The service type
+ * @return The service type in string format
+ */
+ public static String serviceTypeToString(@ServiceType int serviceType) {
+ switch (serviceType) {
+ case SERVICE_TYPE_VOICE: return "VOICE";
+ case SERVICE_TYPE_DATA: return "DATA";
+ case SERVICE_TYPE_SMS: return "SMS";
+ case SERVICE_TYPE_VIDEO: return "VIDEO";
+ case SERVICE_TYPE_EMERGENCY: return "EMERGENCY";
+ }
+ return "Unknown service type " + serviceType;
+ }
+
+ /**
+ * Convert registration state to string
+ *
+ * @hide
+ *
+ * @param regState The registration state
+ * @return The reg state in string
+ */
+ public static String regStateToString(@RegState int regState) {
switch (regState) {
case REG_STATE_NOT_REG_NOT_SEARCHING: return "NOT_REG_NOT_SEARCHING";
case REG_STATE_HOME: return "HOME";
@@ -389,14 +417,17 @@ public class NetworkRegistrationState implements Parcelable {
public String toString() {
return new StringBuilder("NetworkRegistrationState{")
.append(" domain=").append((mDomain == DOMAIN_CS) ? "CS" : "PS")
- .append("transportType=").append(mTransportType)
+ .append(" transportType=").append(TransportType.toString(mTransportType))
.append(" regState=").append(regStateToString(mRegState))
- .append(" roamingType=").append(mRoamingType)
+ .append(" roamingType=").append(ServiceState.roamingTypeToString(mRoamingType))
.append(" accessNetworkTechnology=")
.append(TelephonyManager.getNetworkTypeName(mAccessNetworkTechnology))
.append(" rejectCause=").append(mRejectCause)
.append(" emergencyEnabled=").append(mEmergencyOnly)
- .append(" supportedServices=").append(mAvailableServices)
+ .append(" availableServices=").append("[" + (mAvailableServices != null
+ ? Arrays.stream(mAvailableServices)
+ .mapToObj(type -> serviceTypeToString(type))
+ .collect(Collectors.joining(",")) : null) + "]")
.append(" cellIdentity=").append(mCellIdentity)
.append(" voiceSpecificStates=").append(mVoiceSpecificStates)
.append(" dataSpecificStates=").append(mDataSpecificStates)
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 33178766f3a3..402763e52cfa 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -887,6 +887,24 @@ public class ServiceState implements Parcelable {
}
/**
+ * Convert roaming type to string
+ *
+ * @param roamingType roaming type
+ * @return The roaming type in string format
+ *
+ * @hide
+ */
+ public static String roamingTypeToString(@RoamingType int roamingType) {
+ switch (roamingType) {
+ case ROAMING_TYPE_NOT_ROAMING: return "NOT_ROAMING";
+ case ROAMING_TYPE_UNKNOWN: return "UNKNOWN";
+ case ROAMING_TYPE_DOMESTIC: return "DOMESTIC";
+ case ROAMING_TYPE_INTERNATIONAL: return "INTERNATIONAL";
+ }
+ return "Unknown roaming type " + roamingType;
+ }
+
+ /**
* Convert radio technology to String
*
* @param rt radioTechnology