diff options
| -rw-r--r-- | cmds/statsd/src/StatsLogProcessor.cpp | 17 | ||||
| -rw-r--r-- | cmds/statsd/src/packages/UidMap.cpp | 25 | ||||
| -rw-r--r-- | cmds/statsd/src/packages/UidMap.h | 11 | ||||
| -rw-r--r-- | cmds/statsd/src/stats_events.proto | 22 | ||||
| -rw-r--r-- | cmds/statsd/tests/UidMap_test.cpp | 28 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 9 |
6 files changed, 107 insertions, 5 deletions
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 8910523aeda3..f0689d2cc839 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -15,6 +15,7 @@ */ #include "Log.h" +#include "statslog.h" #include "StatsLogProcessor.h" #include "frameworks/base/cmds/statsd/src/stats_log.pb.h" @@ -48,6 +49,22 @@ void StatsLogProcessor::OnLogEvent(const LogEvent& msg) { pair.second->onLogEvent(msg); flushIfNecessary(msg.GetTimestampNs(), pair.first, pair.second); } + + // Hard-coded logic to update the isolated uid's in the uid-map. + // The field numbers need to be currently updated by hand with stats_events.proto + if (msg.GetTagId() == android::util::ISOLATED_UID_CHANGED) { + status_t err = NO_ERROR, err2 = NO_ERROR, err3 = NO_ERROR; + bool is_create = msg.GetBool(3, &err); + auto parent_uid = int(msg.GetLong(1, &err2)); + auto isolated_uid = int(msg.GetLong(2, &err3)); + if (err == NO_ERROR && err2 == NO_ERROR && err3 == NO_ERROR) { + if (is_create) { + mUidMap->assignIsolatedUid(isolated_uid, parent_uid); + } else { + mUidMap->removeIsolatedUid(isolated_uid, parent_uid); + } + } + } } void StatsLogProcessor::OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config) { diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp index d83c3a426685..7b276421a259 100644 --- a/cmds/statsd/src/packages/UidMap.cpp +++ b/cmds/statsd/src/packages/UidMap.cpp @@ -150,6 +150,31 @@ void UidMap::removeListener(sp<PackageInfoListener> producer) { mSubscribers.erase(producer); } +void UidMap::assignIsolatedUid(int isolatedUid, int parentUid) { + lock_guard<mutex> lock(mIsolatedMutex); + + mIsolatedUidMap[isolatedUid] = parentUid; +} + +void UidMap::removeIsolatedUid(int isolatedUid, int parentUid) { + lock_guard<mutex> lock(mIsolatedMutex); + + auto it = mIsolatedUidMap.find(isolatedUid); + if (it != mIsolatedUidMap.end()) { + mIsolatedUidMap.erase(it); + } +} + +int UidMap::getParentUidOrSelf(int uid) { + lock_guard<mutex> lock(mIsolatedMutex); + + auto it = mIsolatedUidMap.find(uid); + if (it != mIsolatedUidMap.end()) { + return it->second; + } + return uid; +} + void UidMap::clearOutput() { mOutput.Clear(); diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h index bf120e04d7c8..de68fbceb7a9 100644 --- a/cmds/statsd/src/packages/UidMap.h +++ b/cmds/statsd/src/packages/UidMap.h @@ -84,6 +84,12 @@ public: // Informs uid map that a config is removed. Used for keeping mConfigKeys up to date. void OnConfigRemoved(const ConfigKey& key); + void assignIsolatedUid(int isolatedUid, int parentUid); + void removeIsolatedUid(int isolatedUid, int parentUid); + + // Returns the parent uid if it exists. Otherwise, returns the same uid that was passed-in. + int getParentUidOrSelf(int uid); + // Gets the output. If every config key has received the output, then the output is cleared. UidMapping getOutput(const ConfigKey& key); @@ -105,11 +111,16 @@ private: // TODO: Use shared_mutex for improved read-locking if a library can be found in Android. mutable mutex mMutex; + mutable mutex mIsolatedMutex; // Maps uid to application data. This must be multimap since there is a feature in Android for // multiple apps to share the same uid. std::unordered_multimap<int, AppData> mMap; + // Maps isolated uid to the parent uid. Any metrics for an isolated uid will instead contribute + // to the parent uid. + std::unordered_map<int, int> mIsolatedUidMap; + // We prepare the output proto as apps are updated, so that we can grab the current output. UidMapping mOutput; diff --git a/cmds/statsd/src/stats_events.proto b/cmds/statsd/src/stats_events.proto index 82d975914682..8816795ed82f 100644 --- a/cmds/statsd/src/stats_events.proto +++ b/cmds/statsd/src/stats_events.proto @@ -72,7 +72,7 @@ message StatsEvent { PhoneSignalStrengthChanged phone_signal_strength_changed = 40; SettingChanged setting_changed = 41; ActivityForegroundStateChanged activity_foreground_state_changed = 42; - + IsolatedUidChanged isolated_uid_changed = 43; // TODO: Reorder the numbering so that the most frequent occur events occur in the first 15. } @@ -695,7 +695,6 @@ message SettingChanged { optional int32 user = 7; } - /* * Logs activity going to foreground or background * @@ -848,3 +847,22 @@ message PowerStateSubsystemSleepStatePulled { optional uint64 last_entry_timestamp_ms = 5; optional bool supported_only_in_suspend = 6; } + +/** + * Logs creation or removal of an isolated uid. Isolated uid's are temporary uid's to sandbox risky + * behavior in its own uid. However, the metrics of these isolated uid's almost always should be + * attributed back to the parent (host) uid. One example is Chrome. + * + * Logged from: + * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java + */ +message IsolatedUidChanged { + // The host UID. Generally, we should attribute metrics from the isolated uid to the host uid. + optional int32 parent_uid = 1; + + optional int32 isolated_uid = 2; + + // 1 denotes we're creating an isolated uid and 0 denotes removal. We expect an isolated uid to + // be removed before if it's used for another parent uid. + optional int32 is_create = 3; +} diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp index 671f6d4ac472..c64719ee0c85 100644 --- a/cmds/statsd/tests/UidMap_test.cpp +++ b/cmds/statsd/tests/UidMap_test.cpp @@ -13,7 +13,10 @@ // limitations under the License. #include "packages/UidMap.h" +#include "StatsLogProcessor.h" #include "config/ConfigKey.h" +#include "logd/LogEvent.h" +#include "statslog.h" #include <gtest/gtest.h> @@ -29,6 +32,31 @@ namespace statsd { const string kApp1 = "app1.sharing.1"; const string kApp2 = "app2.sharing.1"; +TEST(UidMapTest, TestIsolatedUID) { + sp<UidMap> m = new UidMap(); + StatsLogProcessor p(m, nullptr); + LogEvent addEvent(android::util::ISOLATED_UID_CHANGED, 1); + android_log_event_list* list = addEvent.GetAndroidLogEventList(); + *list << 100; // parent UID + *list << 101; // isolated UID + *list << 1; // Indicates creation. + addEvent.init(); + + EXPECT_EQ(101, m->getParentUidOrSelf(101)); + + p.OnLogEvent(addEvent); + EXPECT_EQ(100, m->getParentUidOrSelf(101)); + + LogEvent removeEvent(android::util::ISOLATED_UID_CHANGED, 1); + list = removeEvent.GetAndroidLogEventList(); + *list << 100; // parent UID + *list << 101; // isolated UID + *list << 0; // Indicates removal. + removeEvent.init(); + p.OnLogEvent(removeEvent); + EXPECT_EQ(101, m->getParentUidOrSelf(101)); +} + TEST(UidMapTest, TestMatching) { UidMap m; vector<int32_t> uids; diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 2ec64a5ecdc4..f2483c0a71e5 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -3639,6 +3639,7 @@ public class BatteryStatsImpl extends BatteryStats { public void addIsolatedUidLocked(int isolatedUid, int appUid) { mIsolatedUids.put(isolatedUid, appUid); + StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, appUid, isolatedUid, 1); } /** @@ -3659,9 +3660,11 @@ public class BatteryStatsImpl extends BatteryStats { * @see #scheduleRemoveIsolatedUidLocked(int, int) */ public void removeIsolatedUidLocked(int isolatedUid) { - mIsolatedUids.delete(isolatedUid); - mKernelUidCpuTimeReader.removeUid(isolatedUid); - mKernelUidCpuFreqTimeReader.removeUid(isolatedUid); + StatsLog.write( + StatsLog.ISOLATED_UID_CHANGED, mIsolatedUids.get(isolatedUid, -1), isolatedUid, 0); + mIsolatedUids.delete(isolatedUid); + mKernelUidCpuTimeReader.removeUid(isolatedUid); + mKernelUidCpuFreqTimeReader.removeUid(isolatedUid); } public int mapUid(int uid) { |