1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define DEBUG false 18 #include "Log.h" 19 20 #include <android/os/IStatsCompanionService.h> 21 #include <android/os/IStatsPullerCallback.h> 22 #include <cutils/log.h> 23 #include <math.h> 24 #include <stdint.h> 25 #include <algorithm> 26 #include "../StatsService.h" 27 #include "../logd/LogEvent.h" 28 #include "../stats_log_util.h" 29 #include "../statscompanion_util.h" 30 #include "GpuStatsPuller.h" 31 #include "PowerStatsPuller.h" 32 #include "ResourceHealthManagerPuller.h" 33 #include "StatsCallbackPuller.h" 34 #include "StatsCompanionServicePuller.h" 35 #include "StatsPullerManager.h" 36 #include "SubsystemSleepStatePuller.h" 37 #include "TrainInfoPuller.h" 38 #include "statslog.h" 39 40 #include <iostream> 41 42 using std::make_shared; 43 using std::map; 44 using std::shared_ptr; 45 using std::string; 46 using std::vector; 47 using std::list; 48 49 namespace android { 50 namespace os { 51 namespace statsd { 52 53 // Values smaller than this may require to update the alarm. 54 const int64_t NO_ALARM_UPDATE = INT64_MAX; 55 56 std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { 57 // wifi_bytes_transfer 58 {android::util::WIFI_BYTES_TRANSFER, 59 {.additiveFields = {2, 3, 4, 5}, 60 .puller = new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER)}}, 61 // wifi_bytes_transfer_by_fg_bg 62 {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG, 63 {.additiveFields = {3, 4, 5, 6}, 64 .puller = new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}}, 65 // mobile_bytes_transfer 66 {android::util::MOBILE_BYTES_TRANSFER, 67 {.additiveFields = {2, 3, 4, 5}, 68 .puller = new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}}, 69 // mobile_bytes_transfer_by_fg_bg 70 {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG, 71 {.additiveFields = {3, 4, 5, 6}, 72 .puller = 73 new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}}, 74 // bluetooth_bytes_transfer 75 {android::util::BLUETOOTH_BYTES_TRANSFER, 76 {.additiveFields = {2, 3}, 77 .puller = new StatsCompanionServicePuller(android::util::BLUETOOTH_BYTES_TRANSFER)}}, 78 // kernel_wakelock 79 {android::util::KERNEL_WAKELOCK, 80 {.puller = new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}}, 81 // subsystem_sleep_state 82 {android::util::SUBSYSTEM_SLEEP_STATE, {.puller = new SubsystemSleepStatePuller()}}, 83 // on_device_power_measurement 84 {android::util::ON_DEVICE_POWER_MEASUREMENT, {.puller = new PowerStatsPuller()}}, 85 // cpu_time_per_freq 86 {android::util::CPU_TIME_PER_FREQ, 87 {.additiveFields = {3}, 88 .puller = new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}}, 89 // cpu_time_per_uid 90 {android::util::CPU_TIME_PER_UID, 91 {.additiveFields = {2, 3}, 92 .puller = new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID)}}, 93 // cpu_time_per_uid_freq 94 // the throttling is 3sec, handled in 95 // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader 96 {android::util::CPU_TIME_PER_UID_FREQ, 97 {.additiveFields = {4}, 98 .puller = new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID_FREQ)}}, 99 // cpu_active_time 100 // the throttling is 3sec, handled in 101 // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader 102 {android::util::CPU_ACTIVE_TIME, 103 {.additiveFields = {2}, 104 .puller = new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}}, 105 // cpu_cluster_time 106 // the throttling is 3sec, handled in 107 // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader 108 {android::util::CPU_CLUSTER_TIME, 109 {.additiveFields = {3}, 110 .puller = new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}}, 111 // wifi_activity_energy_info 112 {android::util::WIFI_ACTIVITY_INFO, 113 {.puller = new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_INFO)}}, 114 // modem_activity_info 115 {android::util::MODEM_ACTIVITY_INFO, 116 {.puller = new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}}, 117 // bluetooth_activity_info 118 {android::util::BLUETOOTH_ACTIVITY_INFO, 119 {.puller = new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}}, 120 // system_elapsed_realtime 121 {android::util::SYSTEM_ELAPSED_REALTIME, 122 {.pullTimeoutNs = NS_PER_SEC / 2, 123 .coolDownNs = NS_PER_SEC, 124 .puller = new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME)}}, 125 // system_uptime 126 {android::util::SYSTEM_UPTIME, 127 {.puller = new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}}, 128 // remaining_battery_capacity 129 {android::util::REMAINING_BATTERY_CAPACITY, 130 {.puller = new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}}, 131 // full_battery_capacity 132 {android::util::FULL_BATTERY_CAPACITY, 133 {.puller = new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}}, 134 // battery_voltage 135 {android::util::BATTERY_VOLTAGE, 136 {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}}, 137 // battery_level 138 {android::util::BATTERY_LEVEL, 139 {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}}, 140 // battery_cycle_count 141 {android::util::BATTERY_CYCLE_COUNT, 142 {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}}, 143 // process_memory_state 144 {android::util::PROCESS_MEMORY_STATE, 145 {.additiveFields = {4, 5, 6, 7, 8, 9}, 146 .puller = new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}}, 147 // native_process_memory_state 148 {android::util::NATIVE_PROCESS_MEMORY_STATE, 149 {.additiveFields = {3, 4, 5, 6, 8}, 150 .puller = new StatsCompanionServicePuller(android::util::NATIVE_PROCESS_MEMORY_STATE)}}, 151 // process_memory_high_water_mark 152 {android::util::PROCESS_MEMORY_HIGH_WATER_MARK, 153 {.additiveFields = {3}, 154 .puller = 155 new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}}, 156 // system_ion_heap_size 157 {android::util::SYSTEM_ION_HEAP_SIZE, 158 {.puller = new StatsCompanionServicePuller(android::util::SYSTEM_ION_HEAP_SIZE)}}, 159 // process_system_ion_heap_size 160 {android::util::PROCESS_SYSTEM_ION_HEAP_SIZE, 161 {.puller = new StatsCompanionServicePuller(android::util::PROCESS_SYSTEM_ION_HEAP_SIZE)}}, 162 // temperature 163 {android::util::TEMPERATURE, 164 {.puller = new StatsCompanionServicePuller(android::util::TEMPERATURE)}}, 165 // cooling_device 166 {android::util::COOLING_DEVICE, 167 {.puller = new StatsCompanionServicePuller(android::util::COOLING_DEVICE)}}, 168 // binder_calls 169 {android::util::BINDER_CALLS, 170 {.additiveFields = {4, 5, 6, 8, 12}, 171 .puller = new StatsCompanionServicePuller(android::util::BINDER_CALLS)}}, 172 // binder_calls_exceptions 173 {android::util::BINDER_CALLS_EXCEPTIONS, 174 {.puller = new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}}, 175 // looper_stats 176 {android::util::LOOPER_STATS, 177 {.additiveFields = {5, 6, 7, 8, 9}, 178 .puller = new StatsCompanionServicePuller(android::util::LOOPER_STATS)}}, 179 // Disk Stats 180 {android::util::DISK_STATS, 181 {.puller = new StatsCompanionServicePuller(android::util::DISK_STATS)}}, 182 // Directory usage 183 {android::util::DIRECTORY_USAGE, 184 {.puller = new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}}, 185 // Size of app's code, data, and cache 186 {android::util::APP_SIZE, 187 {.puller = new StatsCompanionServicePuller(android::util::APP_SIZE)}}, 188 // Size of specific categories of files. Eg. Music. 189 {android::util::CATEGORY_SIZE, 190 {.puller = new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}}, 191 // Number of fingerprints enrolled for each user. 192 {android::util::NUM_FINGERPRINTS_ENROLLED, 193 {.puller = new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS_ENROLLED)}}, 194 // Number of faces enrolled for each user. 195 {android::util::NUM_FACES_ENROLLED, 196 {.puller = new StatsCompanionServicePuller(android::util::NUM_FACES_ENROLLED)}}, 197 // ProcStats. 198 {android::util::PROC_STATS, 199 {.puller = new StatsCompanionServicePuller(android::util::PROC_STATS)}}, 200 // ProcStatsPkgProc. 201 {android::util::PROC_STATS_PKG_PROC, 202 {.puller = new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}}, 203 // Disk I/O stats per uid. 204 {android::util::DISK_IO, 205 {.additiveFields = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 206 .coolDownNs = 3 * NS_PER_SEC, 207 .puller = new StatsCompanionServicePuller(android::util::DISK_IO)}}, 208 // PowerProfile constants for power model calculations. 209 {android::util::POWER_PROFILE, 210 {.puller = new StatsCompanionServicePuller(android::util::POWER_PROFILE)}}, 211 // Process cpu stats. Min cool-down is 5 sec, inline with what AcitivityManagerService uses. 212 {android::util::PROCESS_CPU_TIME, 213 {.coolDownNs = 5 * NS_PER_SEC /* min cool-down in seconds*/, 214 .puller = new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}}, 215 {android::util::CPU_TIME_PER_THREAD_FREQ, 216 {.additiveFields = {7, 9, 11, 13, 15, 17, 19, 21}, 217 .puller = new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}}, 218 // DeviceCalculatedPowerUse. 219 {android::util::DEVICE_CALCULATED_POWER_USE, 220 {.puller = new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_USE)}}, 221 // DeviceCalculatedPowerBlameUid. 222 {android::util::DEVICE_CALCULATED_POWER_BLAME_UID, 223 {.puller = new StatsCompanionServicePuller( 224 android::util::DEVICE_CALCULATED_POWER_BLAME_UID)}}, 225 // DeviceCalculatedPowerBlameOther. 226 {android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER, 227 {.puller = new StatsCompanionServicePuller( 228 android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER)}}, 229 // DebugElapsedClock. 230 {android::util::DEBUG_ELAPSED_CLOCK, 231 {.additiveFields = {1, 2, 3, 4}, 232 .puller = new StatsCompanionServicePuller(android::util::DEBUG_ELAPSED_CLOCK)}}, 233 // DebugFailingElapsedClock. 234 {android::util::DEBUG_FAILING_ELAPSED_CLOCK, 235 {.additiveFields = {1, 2, 3, 4}, 236 .puller = new StatsCompanionServicePuller(android::util::DEBUG_FAILING_ELAPSED_CLOCK)}}, 237 // BuildInformation. 238 {android::util::BUILD_INFORMATION, 239 {.puller = new StatsCompanionServicePuller(android::util::BUILD_INFORMATION)}}, 240 // RoleHolder. 241 {android::util::ROLE_HOLDER, 242 {.puller = new StatsCompanionServicePuller(android::util::ROLE_HOLDER)}}, 243 // PermissionState. 244 {android::util::DANGEROUS_PERMISSION_STATE, 245 {.puller = new StatsCompanionServicePuller(android::util::DANGEROUS_PERMISSION_STATE)}}, 246 // TrainInfo. 247 {android::util::TRAIN_INFO, {.puller = new TrainInfoPuller()}}, 248 // TimeZoneDataInfo. 249 {android::util::TIME_ZONE_DATA_INFO, 250 {.puller = new StatsCompanionServicePuller(android::util::TIME_ZONE_DATA_INFO)}}, 251 // ExternalStorageInfo 252 {android::util::EXTERNAL_STORAGE_INFO, 253 {.puller = new StatsCompanionServicePuller(android::util::EXTERNAL_STORAGE_INFO)}}, 254 // GpuStatsGlobalInfo 255 {android::util::GPU_STATS_GLOBAL_INFO, 256 {.puller = new GpuStatsPuller(android::util::GPU_STATS_GLOBAL_INFO)}}, 257 // GpuStatsAppInfo 258 {android::util::GPU_STATS_APP_INFO, 259 {.puller = new GpuStatsPuller(android::util::GPU_STATS_APP_INFO)}}, 260 // AppsOnExternalStorageInfo 261 {android::util::APPS_ON_EXTERNAL_STORAGE_INFO, 262 {.puller = new StatsCompanionServicePuller(android::util::APPS_ON_EXTERNAL_STORAGE_INFO)}}, 263 // Face Settings 264 {android::util::FACE_SETTINGS, 265 {.puller = new StatsCompanionServicePuller(android::util::FACE_SETTINGS)}}, 266 // App ops 267 {android::util::APP_OPS, 268 {.puller = new StatsCompanionServicePuller(android::util::APP_OPS)}}, 269 }; 270 271 StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) { 272 } 273 274 bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) { 275 VLOG("Initiating pulling %d", tagId); 276 277 if (kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end()) { 278 bool ret = kAllPullAtomInfo.find(tagId)->second.puller->Pull(data); 279 VLOG("pulled %d items", (int)data->size()); 280 if (!ret) { 281 StatsdStats::getInstance().notePullFailed(tagId); 282 } 283 return ret; 284 } else { 285 VLOG("Unknown tagId %d", tagId); 286 return false; // Return early since we don't know what to pull. 287 } 288 } 289 290 bool StatsPullerManager::PullerForMatcherExists(int tagId) const { 291 // Vendor pulled atoms might be registered after we parse the config. 292 return isVendorPulledAtom(tagId) || kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end(); 293 } 294 295 void StatsPullerManager::updateAlarmLocked() { 296 if (mNextPullTimeNs == NO_ALARM_UPDATE) { 297 VLOG("No need to set alarms. Skipping"); 298 return; 299 } 300 301 sp<IStatsCompanionService> statsCompanionServiceCopy = mStatsCompanionService; 302 if (statsCompanionServiceCopy != nullptr) { 303 statsCompanionServiceCopy->setPullingAlarm(mNextPullTimeNs / 1000000); 304 } else { 305 VLOG("StatsCompanionService not available. Alarm not set."); 306 } 307 return; 308 } 309 310 void StatsPullerManager::SetStatsCompanionService( 311 sp<IStatsCompanionService> statsCompanionService) { 312 AutoMutex _l(mLock); 313 sp<IStatsCompanionService> tmpForLock = mStatsCompanionService; 314 mStatsCompanionService = statsCompanionService; 315 for (const auto& pulledAtom : kAllPullAtomInfo) { 316 pulledAtom.second.puller->SetStatsCompanionService(statsCompanionService); 317 } 318 if (mStatsCompanionService != nullptr) { 319 updateAlarmLocked(); 320 } 321 } 322 323 void StatsPullerManager::RegisterReceiver(int tagId, wp<PullDataReceiver> receiver, 324 int64_t nextPullTimeNs, int64_t intervalNs) { 325 AutoMutex _l(mLock); 326 auto& receivers = mReceivers[tagId]; 327 for (auto it = receivers.begin(); it != receivers.end(); it++) { 328 if (it->receiver == receiver) { 329 VLOG("Receiver already registered of %d", (int)receivers.size()); 330 return; 331 } 332 } 333 ReceiverInfo receiverInfo; 334 receiverInfo.receiver = receiver; 335 336 // Round it to the nearest minutes. This is the limit of alarm manager. 337 // In practice, we should always have larger buckets. 338 int64_t roundedIntervalNs = intervalNs / NS_PER_SEC / 60 * NS_PER_SEC * 60; 339 // Scheduled pulling should be at least 1 min apart. 340 // This can be lower in cts tests, in which case we round it to 1 min. 341 if (roundedIntervalNs < 60 * (int64_t)NS_PER_SEC) { 342 roundedIntervalNs = 60 * (int64_t)NS_PER_SEC; 343 } 344 345 receiverInfo.intervalNs = roundedIntervalNs; 346 receiverInfo.nextPullTimeNs = nextPullTimeNs; 347 receivers.push_back(receiverInfo); 348 349 // There is only one alarm for all pulled events. So only set it to the smallest denom. 350 if (nextPullTimeNs < mNextPullTimeNs) { 351 VLOG("Updating next pull time %lld", (long long)mNextPullTimeNs); 352 mNextPullTimeNs = nextPullTimeNs; 353 updateAlarmLocked(); 354 } 355 VLOG("Puller for tagId %d registered of %d", tagId, (int)receivers.size()); 356 } 357 358 void StatsPullerManager::UnRegisterReceiver(int tagId, wp<PullDataReceiver> receiver) { 359 AutoMutex _l(mLock); 360 if (mReceivers.find(tagId) == mReceivers.end()) { 361 VLOG("Unknown pull code or no receivers: %d", tagId); 362 return; 363 } 364 auto& receivers = mReceivers.find(tagId)->second; 365 for (auto it = receivers.begin(); it != receivers.end(); it++) { 366 if (receiver == it->receiver) { 367 receivers.erase(it); 368 VLOG("Puller for tagId %d unregistered of %d", tagId, (int)receivers.size()); 369 return; 370 } 371 } 372 } 373 374 void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) { 375 AutoMutex _l(mLock); 376 int64_t wallClockNs = getWallClockNs(); 377 378 int64_t minNextPullTimeNs = NO_ALARM_UPDATE; 379 380 vector<pair<int, vector<ReceiverInfo*>>> needToPull = 381 vector<pair<int, vector<ReceiverInfo*>>>(); 382 for (auto& pair : mReceivers) { 383 vector<ReceiverInfo*> receivers = vector<ReceiverInfo*>(); 384 if (pair.second.size() != 0) { 385 for (ReceiverInfo& receiverInfo : pair.second) { 386 if (receiverInfo.nextPullTimeNs <= elapsedTimeNs) { 387 receivers.push_back(&receiverInfo); 388 } else { 389 if (receiverInfo.nextPullTimeNs < minNextPullTimeNs) { 390 minNextPullTimeNs = receiverInfo.nextPullTimeNs; 391 } 392 } 393 } 394 if (receivers.size() > 0) { 395 needToPull.push_back(make_pair(pair.first, receivers)); 396 } 397 } 398 } 399 400 for (const auto& pullInfo : needToPull) { 401 vector<shared_ptr<LogEvent>> data; 402 bool pullSuccess = Pull(pullInfo.first, &data); 403 if (pullSuccess) { 404 StatsdStats::getInstance().notePullDelay( 405 pullInfo.first, getElapsedRealtimeNs() - elapsedTimeNs); 406 } else { 407 VLOG("pull failed at %lld, will try again later", (long long)elapsedTimeNs); 408 } 409 410 // Convention is to mark pull atom timestamp at request time. 411 // If we pull at t0, puller starts at t1, finishes at t2, and send back 412 // at t3, we mark t0 as its timestamp, which should correspond to its 413 // triggering event, such as condition change at t0. 414 // Here the triggering event is alarm fired from AlarmManager. 415 // In ValueMetricProducer and GaugeMetricProducer we do same thing 416 // when pull on condition change, etc. 417 for (auto& event : data) { 418 event->setElapsedTimestampNs(elapsedTimeNs); 419 event->setLogdWallClockTimestampNs(wallClockNs); 420 } 421 422 for (const auto& receiverInfo : pullInfo.second) { 423 sp<PullDataReceiver> receiverPtr = receiverInfo->receiver.promote(); 424 if (receiverPtr != nullptr) { 425 receiverPtr->onDataPulled(data, pullSuccess, elapsedTimeNs); 426 // We may have just come out of a coma, compute next pull time. 427 int numBucketsAhead = 428 (elapsedTimeNs - receiverInfo->nextPullTimeNs) / receiverInfo->intervalNs; 429 receiverInfo->nextPullTimeNs += (numBucketsAhead + 1) * receiverInfo->intervalNs; 430 if (receiverInfo->nextPullTimeNs < minNextPullTimeNs) { 431 minNextPullTimeNs = receiverInfo->nextPullTimeNs; 432 } 433 } else { 434 VLOG("receiver already gone."); 435 } 436 } 437 } 438 439 VLOG("mNextPullTimeNs: %lld updated to %lld", (long long)mNextPullTimeNs, 440 (long long)minNextPullTimeNs); 441 mNextPullTimeNs = minNextPullTimeNs; 442 updateAlarmLocked(); 443 } 444 445 int StatsPullerManager::ForceClearPullerCache() { 446 int totalCleared = 0; 447 for (const auto& pulledAtom : kAllPullAtomInfo) { 448 totalCleared += pulledAtom.second.puller->ForceClearCache(); 449 } 450 return totalCleared; 451 } 452 453 int StatsPullerManager::ClearPullerCacheIfNecessary(int64_t timestampNs) { 454 int totalCleared = 0; 455 for (const auto& pulledAtom : kAllPullAtomInfo) { 456 totalCleared += pulledAtom.second.puller->ClearCacheIfNecessary(timestampNs); 457 } 458 return totalCleared; 459 } 460 461 void StatsPullerManager::RegisterPullerCallback(int32_t atomTag, 462 const sp<IStatsPullerCallback>& callback) { 463 AutoMutex _l(mLock); 464 // Platform pullers cannot be changed. 465 if (!isVendorPulledAtom(atomTag)) { 466 VLOG("RegisterPullerCallback: atom tag %d is not vendor pulled", atomTag); 467 return; 468 } 469 VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag); 470 StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true); 471 kAllPullAtomInfo[atomTag] = {.puller = new StatsCallbackPuller(atomTag, callback)}; 472 } 473 474 void StatsPullerManager::UnregisterPullerCallback(int32_t atomTag) { 475 AutoMutex _l(mLock); 476 // Platform pullers cannot be changed. 477 if (!isVendorPulledAtom(atomTag)) { 478 return; 479 } 480 StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/false); 481 kAllPullAtomInfo.erase(atomTag); 482 } 483 484 } // namespace statsd 485 } // namespace os 486 } // namespace android 487