Loading cmds/statsd/src/StatsLogProcessor.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -485,6 +485,15 @@ void StatsLogProcessor::informPullAlarmFired(const int64_t timestampNs) { mStatsPullerManager.OnAlarmFired(timestampNs); } int64_t StatsLogProcessor::getLastReportTimeNs(const ConfigKey& key) { auto it = mMetricsManagers.find(key); if (it == mMetricsManagers.end()) { return 0; } else { return it->second->getLastReportTimeNs(); } } } // namespace statsd } // namespace os } // namespace android cmds/statsd/src/StatsLogProcessor.h +2 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,8 @@ public: void informPullAlarmFired(const int64_t timestampNs); int64_t getLastReportTimeNs(const ConfigKey& key); private: // For testing only. inline sp<AlarmMonitor> getAnomalyAlarmMonitor() const { Loading cmds/statsd/src/StatsService.cpp +125 −92 Original line number Diff line number Diff line Loading @@ -27,8 +27,10 @@ #include "subscriber/SubscriberReporter.h" #include <android-base/file.h> #include <android-base/stringprintf.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/PermissionController.h> #include <dirent.h> #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h> #include <private/android_filesystem_config.h> Loading @@ -42,13 +44,83 @@ using namespace android; using android::base::StringPrintf; namespace android { namespace os { namespace statsd { constexpr const char* kPermissionDump = "android.permission.DUMP"; constexpr const char* kPermissionUsage = "android.permission.PACKAGE_USAGE_STATS"; constexpr const char* kOpUsage = "android:get_usage_stats"; #define STATS_SERVICE_DIR "/data/misc/stats-service" static binder::Status ok() { return binder::Status::ok(); } static binder::Status exception(uint32_t code, const std::string& msg) { ALOGE("%s (%d)", msg.c_str(), code); return binder::Status::fromExceptionCode(code, String8(msg.c_str())); } binder::Status checkUid(uid_t expectedUid) { uid_t uid = IPCThreadState::self()->getCallingUid(); if (uid == expectedUid || uid == AID_ROOT) { return ok(); } else { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d is not expected UID %d", uid, expectedUid)); } } binder::Status checkDumpAndUsageStats(const String16& packageName) { pid_t pid = IPCThreadState::self()->getCallingPid(); uid_t uid = IPCThreadState::self()->getCallingUid(); // Root, system, and shell always have access if (uid == AID_ROOT || uid == AID_SYSTEM || uid == AID_SHELL) { return ok(); } // Caller must be granted these permissions if (!checkCallingPermission(String16(kPermissionDump))) { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionDump)); } if (!checkCallingPermission(String16(kPermissionUsage))) { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionUsage)); } // Caller must also have usage stats op granted PermissionController pc; switch (pc.noteOp(String16(kOpUsage), uid, packageName)) { case PermissionController::MODE_ALLOWED: case PermissionController::MODE_DEFAULT: return ok(); default: return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d / PID %d lacks app-op %s", uid, pid, kOpUsage)); } } #define ENFORCE_UID(uid) { \ binder::Status status = checkUid((uid)); \ if (!status.isOk()) { \ return status; \ } \ } #define ENFORCE_DUMP_AND_USAGE_STATS(packageName) { \ binder::Status status = checkDumpAndUsageStats(packageName); \ if (!status.isOk()) { \ return status; \ } \ } StatsService::StatsService(const sp<Looper>& handlerLooper) : mAnomalyAlarmMonitor(new AlarmMonitor(MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS, [](const sp<IStatsCompanionService>& sc, int64_t timeMillis) { Loading Loading @@ -90,7 +162,7 @@ StatsService::StatsService(const sp<Looper>& handlerLooper) VLOG("Statscompanion could not find a broadcast receiver for %s", key.ToString().c_str()); } else { sc->sendDataBroadcast(receiver); sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key)); } } ); Loading Loading @@ -212,7 +284,10 @@ void StatsService::dump_impl(FILE* out, bool verbose, bool proto) { * Implementation of the adb shell cmd stats command. */ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) { // TODO: Permission check uid_t uid = IPCThreadState::self()->getCallingUid(); if (uid != AID_ROOT && uid != AID_SHELL) { return PERMISSION_DENIED; } const int argCount = args.size(); if (argCount >= 1) { Loading Loading @@ -377,14 +452,15 @@ status_t StatsService::cmd_trigger_broadcast(FILE* out, Vector<String8>& args) { print_cmd_help(out); return UNKNOWN_ERROR; } auto receiver = mConfigManager->GetConfigReceiver(ConfigKey(uid, StrToInt64(name))); ConfigKey key(uid, StrToInt64(name)); auto receiver = mConfigManager->GetConfigReceiver(key); sp<IStatsCompanionService> sc = getStatsCompanionService(); if (sc == nullptr) { VLOG("Could not access statsCompanion"); } else if (receiver == nullptr) { VLOG("Could not find receiver for %s, %s", args[1].c_str(), args[2].c_str()) } else { sc->sendDataBroadcast(receiver); sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key)); VLOG("StatsService::trigger broadcast succeeded to %s, %s", args[1].c_str(), args[2].c_str()); } Loading Loading @@ -660,13 +736,9 @@ status_t StatsService::cmd_clear_puller_cache(FILE* out) { Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version, const vector<String16>& app) { VLOG("StatsService::informAllUidData was called"); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call informAllUidData"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informAllUidData was called"); mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, app); VLOG("StatsService::informAllUidData succeeded"); Loading @@ -674,36 +746,26 @@ Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<i } Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version) { VLOG("StatsService::informOnePackage was called"); ENFORCE_UID(AID_SYSTEM); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call informOnePackage"); } VLOG("StatsService::informOnePackage was called"); mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version); return Status::ok(); } Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) { VLOG("StatsService::informOnePackageRemoved was called"); ENFORCE_UID(AID_SYSTEM); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call informOnePackageRemoved"); } VLOG("StatsService::informOnePackageRemoved was called"); mUidMap->removeApp(getElapsedRealtimeNs(), app, uid); mConfigManager->RemoveConfigs(uid); return Status::ok(); } Status StatsService::informAnomalyAlarmFired() { VLOG("StatsService::informAnomalyAlarmFired was called"); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call informAnomalyAlarmFired"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informAnomalyAlarmFired was called"); int64_t currentTimeSec = getElapsedRealtimeSec(); std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet = mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec)); Loading @@ -717,14 +779,9 @@ Status StatsService::informAnomalyAlarmFired() { } Status StatsService::informAlarmForSubscriberTriggeringFired() { VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called"); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode( Status::EX_SECURITY, "Only system uid can call informAlarmForSubscriberTriggeringFired"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called"); int64_t currentTimeSec = getElapsedRealtimeSec(); std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet = mPeriodicAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec)); Loading @@ -738,44 +795,28 @@ Status StatsService::informAlarmForSubscriberTriggeringFired() { } Status StatsService::informPollAlarmFired() { VLOG("StatsService::informPollAlarmFired was called"); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call informPollAlarmFired"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informPollAlarmFired was called"); mProcessor->informPullAlarmFired(getElapsedRealtimeNs()); VLOG("StatsService::informPollAlarmFired succeeded"); return Status::ok(); } Status StatsService::systemRunning() { if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call systemRunning"); } ENFORCE_UID(AID_SYSTEM); // When system_server is up and running, schedule the dropbox task to run. VLOG("StatsService::systemRunning"); sayHiToStatsCompanion(); return Status::ok(); } Status StatsService::writeDataToDisk() { if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call systemRunning"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::writeDataToDisk"); mProcessor->WriteDataToDisk(); return Status::ok(); } Loading @@ -790,13 +831,9 @@ void StatsService::sayHiToStatsCompanion() { } Status StatsService::statsCompanionReady() { VLOG("StatsService::statsCompanionReady was called"); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call statsCompanionReady"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::statsCompanionReady was called"); sp<IStatsCompanionService> statsCompanion = getStatsCompanionService(); if (statsCompanion == nullptr) { return Status::fromExceptionCode( Loading @@ -820,33 +857,31 @@ void StatsService::OnLogEvent(LogEvent* event, bool reconnectionStarts) { mProcessor->OnLogEvent(event, reconnectionStarts); } Status StatsService::getData(int64_t key, vector<uint8_t>* output) { Status StatsService::getData(int64_t key, const String16& packageName, vector<uint8_t>* output) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid()); if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } ConfigKey configKey(ipc->getCallingUid(), key); mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), false /* include_current_bucket*/, output); return Status::ok(); } Status StatsService::getMetadata(vector<uint8_t>* output) { Status StatsService::getMetadata(const String16& packageName, vector<uint8_t>* output) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); VLOG("StatsService::getMetadata with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid()); if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } StatsdStats::getInstance().dumpStats(output, false); // Don't reset the counters. return Status::ok(); } Status StatsService::addConfiguration(int64_t key, const vector <uint8_t>& config) { if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } Status StatsService::addConfiguration(int64_t key, const vector <uint8_t>& config, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); if (addConfigurationChecked(ipc->getCallingUid(), key, config)) { return Status::ok(); Loading @@ -869,30 +904,29 @@ bool StatsService::addConfigurationChecked(int uid, int64_t key, const vector<ui return true; } Status StatsService::removeDataFetchOperation(int64_t key) { if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } Status StatsService::removeDataFetchOperation(int64_t key, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), key); mConfigManager->RemoveConfigReceiver(configKey); return Status::ok(); } Status StatsService::setDataFetchOperation(int64_t key, const sp<android::IBinder>& intentSender) { if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } Status StatsService::setDataFetchOperation(int64_t key, const sp<android::IBinder>& intentSender, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), key); mConfigManager->SetConfigReceiver(configKey, intentSender); return Status::ok(); } Status StatsService::removeConfiguration(int64_t key) { if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } Status StatsService::removeConfiguration(int64_t key, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), key); mConfigManager->RemoveConfig(configKey); Loading @@ -902,11 +936,11 @@ Status StatsService::removeConfiguration(int64_t key) { Status StatsService::setBroadcastSubscriber(int64_t configId, int64_t subscriberId, const sp<android::IBinder>& intentSender) { const sp<android::IBinder>& intentSender, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); VLOG("StatsService::setBroadcastSubscriber called."); if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), configId); SubscriberReporter::getInstance() Loading @@ -915,11 +949,11 @@ Status StatsService::setBroadcastSubscriber(int64_t configId, } Status StatsService::unsetBroadcastSubscriber(int64_t configId, int64_t subscriberId) { int64_t subscriberId, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); VLOG("StatsService::unsetBroadcastSubscriber called."); if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), configId); SubscriberReporter::getInstance() Loading @@ -927,7 +961,6 @@ Status StatsService::unsetBroadcastSubscriber(int64_t configId, return Status::ok(); } void StatsService::binderDied(const wp <IBinder>& who) { ALOGW("statscompanion service died"); mProcessor->WriteDataToDisk(); Loading cmds/statsd/src/StatsService.h +19 −8 Original line number Diff line number Diff line Loading @@ -81,36 +81,44 @@ public: /** * Binder call for clients to request data for this configuration key. */ virtual Status getData(int64_t key, vector<uint8_t>* output) override; virtual Status getData(int64_t key, const String16& packageName, vector<uint8_t>* output) override; /** * Binder call for clients to get metadata across all configs in statsd. */ virtual Status getMetadata(vector<uint8_t>* output) override; virtual Status getMetadata(const String16& packageName, vector<uint8_t>* output) override; /** * Binder call to let clients send a configuration and indicate they're interested when they * should requestData for this configuration. */ virtual Status addConfiguration(int64_t key, const vector<uint8_t>& config) override; virtual Status addConfiguration(int64_t key, const vector<uint8_t>& config, const String16& packageName) override; /** * Binder call to let clients register the data fetch operation for a configuration. */ virtual Status setDataFetchOperation(int64_t key, const sp<android::IBinder>& intentSender) override; const sp<android::IBinder>& intentSender, const String16& packageName) override; /** * Binder call to remove the data fetch operation for the specified config key. */ virtual Status removeDataFetchOperation(int64_t key) override; virtual Status removeDataFetchOperation(int64_t key, const String16& packageName) override; /** * Binder call to allow clients to remove the specified configuration. */ virtual Status removeConfiguration(int64_t key) override; virtual Status removeConfiguration(int64_t key, const String16& packageName) override; /** * Binder call to associate the given config's subscriberId with the given intentSender. Loading @@ -118,12 +126,15 @@ public: */ virtual Status setBroadcastSubscriber(int64_t configId, int64_t subscriberId, const sp<android::IBinder>& intentSender) override; const sp<android::IBinder>& intentSender, const String16& packageName) override; /** * Binder call to unassociate the given config's subscriberId with any intentSender. */ virtual Status unsetBroadcastSubscriber(int64_t configId, int64_t subscriberId) override; virtual Status unsetBroadcastSubscriber(int64_t configId, int64_t subscriberId, const String16& packageName) override; /** Inform statsCompanion that statsd is ready. */ virtual void sayHiToStatsCompanion(); Loading cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ namespace statsd { #ifdef __ANDROID__ const string kAndroid = "android"; const string kApp1 = "app1.sharing.1"; const int kConfigKey = 789130123; // Randomly chosen to avoid collisions with existing configs. Loading @@ -35,12 +36,12 @@ void SendConfig(StatsService& service, const StatsdConfig& config) { config.SerializeToString(&str); std::vector<uint8_t> configAsVec(str.begin(), str.end()); bool success; service.addConfiguration(kConfigKey, configAsVec); service.addConfiguration(kConfigKey, configAsVec, String16(kAndroid.c_str())); } ConfigMetricsReport GetReports(StatsService& service) { vector<uint8_t> output; service.getData(kConfigKey, &output); service.getData(kConfigKey, String16(kAndroid.c_str()), &output); ConfigMetricsReportList reports; reports.ParseFromArray(output.data(), output.size()); EXPECT_EQ(1, reports.reports_size()); Loading Loading
cmds/statsd/src/StatsLogProcessor.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -485,6 +485,15 @@ void StatsLogProcessor::informPullAlarmFired(const int64_t timestampNs) { mStatsPullerManager.OnAlarmFired(timestampNs); } int64_t StatsLogProcessor::getLastReportTimeNs(const ConfigKey& key) { auto it = mMetricsManagers.find(key); if (it == mMetricsManagers.end()) { return 0; } else { return it->second->getLastReportTimeNs(); } } } // namespace statsd } // namespace os } // namespace android
cmds/statsd/src/StatsLogProcessor.h +2 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,8 @@ public: void informPullAlarmFired(const int64_t timestampNs); int64_t getLastReportTimeNs(const ConfigKey& key); private: // For testing only. inline sp<AlarmMonitor> getAnomalyAlarmMonitor() const { Loading
cmds/statsd/src/StatsService.cpp +125 −92 Original line number Diff line number Diff line Loading @@ -27,8 +27,10 @@ #include "subscriber/SubscriberReporter.h" #include <android-base/file.h> #include <android-base/stringprintf.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/PermissionController.h> #include <dirent.h> #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h> #include <private/android_filesystem_config.h> Loading @@ -42,13 +44,83 @@ using namespace android; using android::base::StringPrintf; namespace android { namespace os { namespace statsd { constexpr const char* kPermissionDump = "android.permission.DUMP"; constexpr const char* kPermissionUsage = "android.permission.PACKAGE_USAGE_STATS"; constexpr const char* kOpUsage = "android:get_usage_stats"; #define STATS_SERVICE_DIR "/data/misc/stats-service" static binder::Status ok() { return binder::Status::ok(); } static binder::Status exception(uint32_t code, const std::string& msg) { ALOGE("%s (%d)", msg.c_str(), code); return binder::Status::fromExceptionCode(code, String8(msg.c_str())); } binder::Status checkUid(uid_t expectedUid) { uid_t uid = IPCThreadState::self()->getCallingUid(); if (uid == expectedUid || uid == AID_ROOT) { return ok(); } else { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d is not expected UID %d", uid, expectedUid)); } } binder::Status checkDumpAndUsageStats(const String16& packageName) { pid_t pid = IPCThreadState::self()->getCallingPid(); uid_t uid = IPCThreadState::self()->getCallingUid(); // Root, system, and shell always have access if (uid == AID_ROOT || uid == AID_SYSTEM || uid == AID_SHELL) { return ok(); } // Caller must be granted these permissions if (!checkCallingPermission(String16(kPermissionDump))) { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionDump)); } if (!checkCallingPermission(String16(kPermissionUsage))) { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionUsage)); } // Caller must also have usage stats op granted PermissionController pc; switch (pc.noteOp(String16(kOpUsage), uid, packageName)) { case PermissionController::MODE_ALLOWED: case PermissionController::MODE_DEFAULT: return ok(); default: return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d / PID %d lacks app-op %s", uid, pid, kOpUsage)); } } #define ENFORCE_UID(uid) { \ binder::Status status = checkUid((uid)); \ if (!status.isOk()) { \ return status; \ } \ } #define ENFORCE_DUMP_AND_USAGE_STATS(packageName) { \ binder::Status status = checkDumpAndUsageStats(packageName); \ if (!status.isOk()) { \ return status; \ } \ } StatsService::StatsService(const sp<Looper>& handlerLooper) : mAnomalyAlarmMonitor(new AlarmMonitor(MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS, [](const sp<IStatsCompanionService>& sc, int64_t timeMillis) { Loading Loading @@ -90,7 +162,7 @@ StatsService::StatsService(const sp<Looper>& handlerLooper) VLOG("Statscompanion could not find a broadcast receiver for %s", key.ToString().c_str()); } else { sc->sendDataBroadcast(receiver); sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key)); } } ); Loading Loading @@ -212,7 +284,10 @@ void StatsService::dump_impl(FILE* out, bool verbose, bool proto) { * Implementation of the adb shell cmd stats command. */ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) { // TODO: Permission check uid_t uid = IPCThreadState::self()->getCallingUid(); if (uid != AID_ROOT && uid != AID_SHELL) { return PERMISSION_DENIED; } const int argCount = args.size(); if (argCount >= 1) { Loading Loading @@ -377,14 +452,15 @@ status_t StatsService::cmd_trigger_broadcast(FILE* out, Vector<String8>& args) { print_cmd_help(out); return UNKNOWN_ERROR; } auto receiver = mConfigManager->GetConfigReceiver(ConfigKey(uid, StrToInt64(name))); ConfigKey key(uid, StrToInt64(name)); auto receiver = mConfigManager->GetConfigReceiver(key); sp<IStatsCompanionService> sc = getStatsCompanionService(); if (sc == nullptr) { VLOG("Could not access statsCompanion"); } else if (receiver == nullptr) { VLOG("Could not find receiver for %s, %s", args[1].c_str(), args[2].c_str()) } else { sc->sendDataBroadcast(receiver); sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key)); VLOG("StatsService::trigger broadcast succeeded to %s, %s", args[1].c_str(), args[2].c_str()); } Loading Loading @@ -660,13 +736,9 @@ status_t StatsService::cmd_clear_puller_cache(FILE* out) { Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version, const vector<String16>& app) { VLOG("StatsService::informAllUidData was called"); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call informAllUidData"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informAllUidData was called"); mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, app); VLOG("StatsService::informAllUidData succeeded"); Loading @@ -674,36 +746,26 @@ Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<i } Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version) { VLOG("StatsService::informOnePackage was called"); ENFORCE_UID(AID_SYSTEM); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call informOnePackage"); } VLOG("StatsService::informOnePackage was called"); mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version); return Status::ok(); } Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) { VLOG("StatsService::informOnePackageRemoved was called"); ENFORCE_UID(AID_SYSTEM); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call informOnePackageRemoved"); } VLOG("StatsService::informOnePackageRemoved was called"); mUidMap->removeApp(getElapsedRealtimeNs(), app, uid); mConfigManager->RemoveConfigs(uid); return Status::ok(); } Status StatsService::informAnomalyAlarmFired() { VLOG("StatsService::informAnomalyAlarmFired was called"); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call informAnomalyAlarmFired"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informAnomalyAlarmFired was called"); int64_t currentTimeSec = getElapsedRealtimeSec(); std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet = mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec)); Loading @@ -717,14 +779,9 @@ Status StatsService::informAnomalyAlarmFired() { } Status StatsService::informAlarmForSubscriberTriggeringFired() { VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called"); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode( Status::EX_SECURITY, "Only system uid can call informAlarmForSubscriberTriggeringFired"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called"); int64_t currentTimeSec = getElapsedRealtimeSec(); std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet = mPeriodicAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec)); Loading @@ -738,44 +795,28 @@ Status StatsService::informAlarmForSubscriberTriggeringFired() { } Status StatsService::informPollAlarmFired() { VLOG("StatsService::informPollAlarmFired was called"); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call informPollAlarmFired"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::informPollAlarmFired was called"); mProcessor->informPullAlarmFired(getElapsedRealtimeNs()); VLOG("StatsService::informPollAlarmFired succeeded"); return Status::ok(); } Status StatsService::systemRunning() { if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call systemRunning"); } ENFORCE_UID(AID_SYSTEM); // When system_server is up and running, schedule the dropbox task to run. VLOG("StatsService::systemRunning"); sayHiToStatsCompanion(); return Status::ok(); } Status StatsService::writeDataToDisk() { if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call systemRunning"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::writeDataToDisk"); mProcessor->WriteDataToDisk(); return Status::ok(); } Loading @@ -790,13 +831,9 @@ void StatsService::sayHiToStatsCompanion() { } Status StatsService::statsCompanionReady() { VLOG("StatsService::statsCompanionReady was called"); if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, "Only system uid can call statsCompanionReady"); } ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::statsCompanionReady was called"); sp<IStatsCompanionService> statsCompanion = getStatsCompanionService(); if (statsCompanion == nullptr) { return Status::fromExceptionCode( Loading @@ -820,33 +857,31 @@ void StatsService::OnLogEvent(LogEvent* event, bool reconnectionStarts) { mProcessor->OnLogEvent(event, reconnectionStarts); } Status StatsService::getData(int64_t key, vector<uint8_t>* output) { Status StatsService::getData(int64_t key, const String16& packageName, vector<uint8_t>* output) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid()); if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } ConfigKey configKey(ipc->getCallingUid(), key); mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), false /* include_current_bucket*/, output); return Status::ok(); } Status StatsService::getMetadata(vector<uint8_t>* output) { Status StatsService::getMetadata(const String16& packageName, vector<uint8_t>* output) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); VLOG("StatsService::getMetadata with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid()); if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } StatsdStats::getInstance().dumpStats(output, false); // Don't reset the counters. return Status::ok(); } Status StatsService::addConfiguration(int64_t key, const vector <uint8_t>& config) { if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } Status StatsService::addConfiguration(int64_t key, const vector <uint8_t>& config, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); if (addConfigurationChecked(ipc->getCallingUid(), key, config)) { return Status::ok(); Loading @@ -869,30 +904,29 @@ bool StatsService::addConfigurationChecked(int uid, int64_t key, const vector<ui return true; } Status StatsService::removeDataFetchOperation(int64_t key) { if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } Status StatsService::removeDataFetchOperation(int64_t key, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), key); mConfigManager->RemoveConfigReceiver(configKey); return Status::ok(); } Status StatsService::setDataFetchOperation(int64_t key, const sp<android::IBinder>& intentSender) { if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } Status StatsService::setDataFetchOperation(int64_t key, const sp<android::IBinder>& intentSender, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), key); mConfigManager->SetConfigReceiver(configKey, intentSender); return Status::ok(); } Status StatsService::removeConfiguration(int64_t key) { if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } Status StatsService::removeConfiguration(int64_t key, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), key); mConfigManager->RemoveConfig(configKey); Loading @@ -902,11 +936,11 @@ Status StatsService::removeConfiguration(int64_t key) { Status StatsService::setBroadcastSubscriber(int64_t configId, int64_t subscriberId, const sp<android::IBinder>& intentSender) { const sp<android::IBinder>& intentSender, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); VLOG("StatsService::setBroadcastSubscriber called."); if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), configId); SubscriberReporter::getInstance() Loading @@ -915,11 +949,11 @@ Status StatsService::setBroadcastSubscriber(int64_t configId, } Status StatsService::unsetBroadcastSubscriber(int64_t configId, int64_t subscriberId) { int64_t subscriberId, const String16& packageName) { ENFORCE_DUMP_AND_USAGE_STATS(packageName); VLOG("StatsService::unsetBroadcastSubscriber called."); if (!checkCallingPermission(String16(kPermissionDump))) { return Status::fromExceptionCode(binder::Status::EX_SECURITY); } IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), configId); SubscriberReporter::getInstance() Loading @@ -927,7 +961,6 @@ Status StatsService::unsetBroadcastSubscriber(int64_t configId, return Status::ok(); } void StatsService::binderDied(const wp <IBinder>& who) { ALOGW("statscompanion service died"); mProcessor->WriteDataToDisk(); Loading
cmds/statsd/src/StatsService.h +19 −8 Original line number Diff line number Diff line Loading @@ -81,36 +81,44 @@ public: /** * Binder call for clients to request data for this configuration key. */ virtual Status getData(int64_t key, vector<uint8_t>* output) override; virtual Status getData(int64_t key, const String16& packageName, vector<uint8_t>* output) override; /** * Binder call for clients to get metadata across all configs in statsd. */ virtual Status getMetadata(vector<uint8_t>* output) override; virtual Status getMetadata(const String16& packageName, vector<uint8_t>* output) override; /** * Binder call to let clients send a configuration and indicate they're interested when they * should requestData for this configuration. */ virtual Status addConfiguration(int64_t key, const vector<uint8_t>& config) override; virtual Status addConfiguration(int64_t key, const vector<uint8_t>& config, const String16& packageName) override; /** * Binder call to let clients register the data fetch operation for a configuration. */ virtual Status setDataFetchOperation(int64_t key, const sp<android::IBinder>& intentSender) override; const sp<android::IBinder>& intentSender, const String16& packageName) override; /** * Binder call to remove the data fetch operation for the specified config key. */ virtual Status removeDataFetchOperation(int64_t key) override; virtual Status removeDataFetchOperation(int64_t key, const String16& packageName) override; /** * Binder call to allow clients to remove the specified configuration. */ virtual Status removeConfiguration(int64_t key) override; virtual Status removeConfiguration(int64_t key, const String16& packageName) override; /** * Binder call to associate the given config's subscriberId with the given intentSender. Loading @@ -118,12 +126,15 @@ public: */ virtual Status setBroadcastSubscriber(int64_t configId, int64_t subscriberId, const sp<android::IBinder>& intentSender) override; const sp<android::IBinder>& intentSender, const String16& packageName) override; /** * Binder call to unassociate the given config's subscriberId with any intentSender. */ virtual Status unsetBroadcastSubscriber(int64_t configId, int64_t subscriberId) override; virtual Status unsetBroadcastSubscriber(int64_t configId, int64_t subscriberId, const String16& packageName) override; /** Inform statsCompanion that statsd is ready. */ virtual void sayHiToStatsCompanion(); Loading
cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ namespace statsd { #ifdef __ANDROID__ const string kAndroid = "android"; const string kApp1 = "app1.sharing.1"; const int kConfigKey = 789130123; // Randomly chosen to avoid collisions with existing configs. Loading @@ -35,12 +36,12 @@ void SendConfig(StatsService& service, const StatsdConfig& config) { config.SerializeToString(&str); std::vector<uint8_t> configAsVec(str.begin(), str.end()); bool success; service.addConfiguration(kConfigKey, configAsVec); service.addConfiguration(kConfigKey, configAsVec, String16(kAndroid.c_str())); } ConfigMetricsReport GetReports(StatsService& service) { vector<uint8_t> output; service.getData(kConfigKey, &output); service.getData(kConfigKey, String16(kAndroid.c_str()), &output); ConfigMetricsReportList reports; reports.ParseFromArray(output.data(), output.size()); EXPECT_EQ(1, reports.reports_size()); Loading