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 <cutils/log.h> 22 #include <math.h> 23 #include <stdint.h> 24 #include <algorithm> 25 #include "../StatsService.h" 26 #include "../logd/LogEvent.h" 27 #include "../stats_log_util.h" 28 #include "../statscompanion_util.h" 29 #include "ResourceHealthManagerPuller.h" 30 #include "ResourceThermalManagerPuller.h" 31 #include "StatsCompanionServicePuller.h" 32 #include "StatsPullerManagerImpl.h" 33 #include "SubsystemSleepStatePuller.h" 34 #include "statslog.h" 35 36 #include <iostream> 37 38 using std::make_shared; 39 using std::map; 40 using std::shared_ptr; 41 using std::string; 42 using std::vector; 43 using std::list; 44 45 namespace android { 46 namespace os { 47 namespace statsd { 48 49 // Values smaller than this may require to update the alarm. 50 const int64_t NO_ALARM_UPDATE = INT64_MAX; 51 52 const std::map<int, PullAtomInfo> StatsPullerManagerImpl::kAllPullAtomInfo = { 53 // wifi_bytes_transfer 54 {android::util::WIFI_BYTES_TRANSFER, 55 {{2, 3, 4, 5}, 56 {}, 57 1 * NS_PER_SEC, 58 new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER)}}, 59 // wifi_bytes_transfer_by_fg_bg 60 {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG, 61 {{3, 4, 5, 6}, 62 {2}, 63 1 * NS_PER_SEC, 64 new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}}, 65 // mobile_bytes_transfer 66 {android::util::MOBILE_BYTES_TRANSFER, 67 {{2, 3, 4, 5}, 68 {}, 69 1 * NS_PER_SEC, 70 new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}}, 71 // mobile_bytes_transfer_by_fg_bg 72 {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG, 73 {{3, 4, 5, 6}, 74 {2}, 75 1 * NS_PER_SEC, 76 new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}}, 77 // bluetooth_bytes_transfer 78 {android::util::BLUETOOTH_BYTES_TRANSFER, 79 {{2, 3}, 80 {}, 81 1 * NS_PER_SEC, 82 new StatsCompanionServicePuller(android::util::BLUETOOTH_BYTES_TRANSFER)}}, 83 // kernel_wakelock 84 {android::util::KERNEL_WAKELOCK, 85 {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}}, 86 // subsystem_sleep_state 87 {android::util::SUBSYSTEM_SLEEP_STATE, 88 {{}, {}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}}, 89 // cpu_time_per_freq 90 {android::util::CPU_TIME_PER_FREQ, 91 {{3}, 92 {2}, 93 1 * NS_PER_SEC, 94 new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}}, 95 // cpu_time_per_uid 96 {android::util::CPU_TIME_PER_UID, 97 {{2, 3}, 98 {}, 99 1 * NS_PER_SEC, 100 new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID)}}, 101 // cpu_time_per_uid_freq 102 // the throttling is 3sec, handled in 103 // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader 104 {android::util::CPU_TIME_PER_UID_FREQ, 105 {{4}, 106 {2, 3}, 107 1 * NS_PER_SEC, 108 new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID_FREQ)}}, 109 // cpu_active_time 110 // the throttling is 3sec, handled in 111 // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader 112 {android::util::CPU_ACTIVE_TIME, 113 {{2}, 114 {}, 115 1 * NS_PER_SEC, 116 new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}}, 117 // cpu_cluster_time 118 // the throttling is 3sec, handled in 119 // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader 120 {android::util::CPU_CLUSTER_TIME, 121 {{3}, 122 {2}, 123 1 * NS_PER_SEC, 124 new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}}, 125 // wifi_activity_energy_info 126 {android::util::WIFI_ACTIVITY_INFO, 127 {{}, 128 {}, 129 1 * NS_PER_SEC, 130 new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_INFO)}}, 131 // modem_activity_info 132 {android::util::MODEM_ACTIVITY_INFO, 133 {{}, 134 {}, 135 1 * NS_PER_SEC, 136 new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}}, 137 // bluetooth_activity_info 138 {android::util::BLUETOOTH_ACTIVITY_INFO, 139 {{}, 140 {}, 141 1 * NS_PER_SEC, 142 new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}}, 143 // system_elapsed_realtime 144 {android::util::SYSTEM_ELAPSED_REALTIME, 145 {{}, 146 {}, 147 1 * NS_PER_SEC, 148 new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME)}}, 149 // system_uptime 150 {android::util::SYSTEM_UPTIME, 151 {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}}, 152 // disk_space 153 {android::util::DISK_SPACE, 154 {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_SPACE)}}, 155 // remaining_battery_capacity 156 {android::util::REMAINING_BATTERY_CAPACITY, 157 {{}, 158 {}, 159 1 * NS_PER_SEC, 160 new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}}, 161 // full_battery_capacity 162 {android::util::FULL_BATTERY_CAPACITY, 163 {{}, 164 {}, 165 1 * NS_PER_SEC, 166 new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}}, 167 // process_memory_state 168 {android::util::PROCESS_MEMORY_STATE, 169 {{4, 5, 6, 7, 8}, 170 {2, 3}, 171 1 * NS_PER_SEC, 172 new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}}, 173 // temperature 174 {android::util::TEMPERATURE, {{}, {}, 1, new ResourceThermalManagerPuller()}}}; 175 176 StatsPullerManagerImpl::StatsPullerManagerImpl() : mNextPullTimeNs(NO_ALARM_UPDATE) { 177 } 178 179 bool StatsPullerManagerImpl::Pull(const int tagId, const int64_t timeNs, 180 vector<shared_ptr<LogEvent>>* data) { 181 VLOG("Initiating pulling %d", tagId); 182 183 if (kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end()) { 184 bool ret = kAllPullAtomInfo.find(tagId)->second.puller->Pull(timeNs, data); 185 VLOG("pulled %d items", (int)data->size()); 186 return ret; 187 } else { 188 VLOG("Unknown tagId %d", tagId); 189 return false; // Return early since we don't know what to pull. 190 } 191 } 192 193 StatsPullerManagerImpl& StatsPullerManagerImpl::GetInstance() { 194 static StatsPullerManagerImpl instance; 195 return instance; 196 } 197 198 bool StatsPullerManagerImpl::PullerForMatcherExists(int tagId) const { 199 return kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end(); 200 } 201 202 void StatsPullerManagerImpl::updateAlarmLocked() { 203 if (mNextPullTimeNs == NO_ALARM_UPDATE) { 204 VLOG("No need to set alarms. Skipping"); 205 return; 206 } 207 208 sp<IStatsCompanionService> statsCompanionServiceCopy = mStatsCompanionService; 209 if (statsCompanionServiceCopy != nullptr) { 210 statsCompanionServiceCopy->setPullingAlarm(mNextPullTimeNs / 1000000); 211 } else { 212 VLOG("StatsCompanionService not available. Alarm not set."); 213 } 214 return; 215 } 216 217 void StatsPullerManagerImpl::SetStatsCompanionService( 218 sp<IStatsCompanionService> statsCompanionService) { 219 AutoMutex _l(mLock); 220 sp<IStatsCompanionService> tmpForLock = mStatsCompanionService; 221 mStatsCompanionService = statsCompanionService; 222 for (const auto& pulledAtom : kAllPullAtomInfo) { 223 pulledAtom.second.puller->SetStatsCompanionService(statsCompanionService); 224 } 225 if (mStatsCompanionService != nullptr) { 226 updateAlarmLocked(); 227 } 228 } 229 230 void StatsPullerManagerImpl::RegisterReceiver(int tagId, wp<PullDataReceiver> receiver, 231 int64_t nextPullTimeNs, int64_t intervalNs) { 232 AutoMutex _l(mLock); 233 auto& receivers = mReceivers[tagId]; 234 for (auto it = receivers.begin(); it != receivers.end(); it++) { 235 if (it->receiver == receiver) { 236 VLOG("Receiver already registered of %d", (int)receivers.size()); 237 return; 238 } 239 } 240 ReceiverInfo receiverInfo; 241 receiverInfo.receiver = receiver; 242 243 // Round it to the nearest minutes. This is the limit of alarm manager. 244 // In practice, we should always have larger buckets. 245 int64_t roundedIntervalNs = intervalNs / NS_PER_SEC / 60 * NS_PER_SEC * 60; 246 // Scheduled pulling should be at least 1 min apart. 247 // This can be lower in cts tests, in which case we round it to 1 min. 248 if (roundedIntervalNs < 60 * (int64_t)NS_PER_SEC) { 249 roundedIntervalNs = 60 * (int64_t)NS_PER_SEC; 250 } 251 252 receiverInfo.intervalNs = roundedIntervalNs; 253 receiverInfo.nextPullTimeNs = nextPullTimeNs; 254 receivers.push_back(receiverInfo); 255 256 // There is only one alarm for all pulled events. So only set it to the smallest denom. 257 if (nextPullTimeNs < mNextPullTimeNs) { 258 VLOG("Updating next pull time %lld", (long long)mNextPullTimeNs); 259 mNextPullTimeNs = nextPullTimeNs; 260 updateAlarmLocked(); 261 } 262 VLOG("Puller for tagId %d registered of %d", tagId, (int)receivers.size()); 263 } 264 265 void StatsPullerManagerImpl::UnRegisterReceiver(int tagId, wp<PullDataReceiver> receiver) { 266 AutoMutex _l(mLock); 267 if (mReceivers.find(tagId) == mReceivers.end()) { 268 VLOG("Unknown pull code or no receivers: %d", tagId); 269 return; 270 } 271 auto& receivers = mReceivers.find(tagId)->second; 272 for (auto it = receivers.begin(); it != receivers.end(); it++) { 273 if (receiver == it->receiver) { 274 receivers.erase(it); 275 VLOG("Puller for tagId %d unregistered of %d", tagId, (int)receivers.size()); 276 return; 277 } 278 } 279 } 280 281 void StatsPullerManagerImpl::OnAlarmFired(const int64_t currentTimeNs) { 282 AutoMutex _l(mLock); 283 284 int64_t minNextPullTimeNs = NO_ALARM_UPDATE; 285 286 vector<pair<int, vector<ReceiverInfo*>>> needToPull = 287 vector<pair<int, vector<ReceiverInfo*>>>(); 288 for (auto& pair : mReceivers) { 289 vector<ReceiverInfo*> receivers = vector<ReceiverInfo*>(); 290 if (pair.second.size() != 0) { 291 for (ReceiverInfo& receiverInfo : pair.second) { 292 if (receiverInfo.nextPullTimeNs <= currentTimeNs) { 293 receivers.push_back(&receiverInfo); 294 } else { 295 if (receiverInfo.nextPullTimeNs < minNextPullTimeNs) { 296 minNextPullTimeNs = receiverInfo.nextPullTimeNs; 297 } 298 } 299 } 300 if (receivers.size() > 0) { 301 needToPull.push_back(make_pair(pair.first, receivers)); 302 } 303 } 304 } 305 306 for (const auto& pullInfo : needToPull) { 307 vector<shared_ptr<LogEvent>> data; 308 if (Pull(pullInfo.first, currentTimeNs, &data)) { 309 for (const auto& receiverInfo : pullInfo.second) { 310 sp<PullDataReceiver> receiverPtr = receiverInfo->receiver.promote(); 311 if (receiverPtr != nullptr) { 312 receiverPtr->onDataPulled(data); 313 // we may have just come out of a coma, compute next pull time 314 receiverInfo->nextPullTimeNs = 315 (currentTimeNs - receiverInfo->nextPullTimeNs) / 316 receiverInfo->intervalNs * receiverInfo->intervalNs + 317 receiverInfo->intervalNs + receiverInfo->nextPullTimeNs; 318 if (receiverInfo->nextPullTimeNs < minNextPullTimeNs) { 319 minNextPullTimeNs = receiverInfo->nextPullTimeNs; 320 } 321 } else { 322 VLOG("receiver already gone."); 323 } 324 } 325 } 326 } 327 328 VLOG("mNextPullTimeNs: %lld updated to %lld", (long long)mNextPullTimeNs, 329 (long long)minNextPullTimeNs); 330 mNextPullTimeNs = minNextPullTimeNs; 331 updateAlarmLocked(); 332 } 333 334 int StatsPullerManagerImpl::ForceClearPullerCache() { 335 int totalCleared = 0; 336 for (const auto& pulledAtom : kAllPullAtomInfo) { 337 totalCleared += pulledAtom.second.puller->ForceClearCache(); 338 } 339 return totalCleared; 340 } 341 342 int StatsPullerManagerImpl::ClearPullerCacheIfNecessary(int64_t timestampNs) { 343 int totalCleared = 0; 344 for (const auto& pulledAtom : kAllPullAtomInfo) { 345 totalCleared += pulledAtom.second.puller->ClearCacheIfNecessary(timestampNs); 346 } 347 return totalCleared; 348 } 349 350 } // namespace statsd 351 } // namespace os 352 } // namespace android 353