Home | History | Annotate | Download | only in external
      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