• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 #include "chre_host/metrics_reporter.h"
18 #include <chre_atoms_log.h>
19 #include "chre_host/log.h"
20 
21 #include <cinttypes>
22 #include <limits>
23 #include <mutex>
24 
25 #include <android/binder_manager.h>
26 
27 namespace android::chre {
28 
29 using ::aidl::android::frameworks::stats::IStats;
30 using ::aidl::android::frameworks::stats::VendorAtom;
31 using ::aidl::android::frameworks::stats::VendorAtomValue;
32 using ::android::chre::Atoms::CHRE_AP_WAKE_UP_OCCURRED;
33 using ::android::chre::Atoms::CHRE_EVENT_QUEUE_SNAPSHOT_REPORTED;
34 using ::android::chre::Atoms::CHRE_HAL_NANOAPP_LOAD_FAILED;
35 using ::android::chre::Atoms::CHRE_PAL_OPEN_FAILED;
36 using ::android::chre::Atoms::ChreHalNanoappLoadFailed;
37 using ::android::chre::Atoms::ChrePalOpenFailed;
38 
getStatsService()39 std::shared_ptr<IStats> MetricsReporter::getStatsService() {
40   const std::string statsServiceName =
41       std::string(IStats::descriptor).append("/default");
42   if (!AServiceManager_isDeclared(statsServiceName.c_str())) {
43     LOGE("Stats service is not declared.");
44     return nullptr;
45   }
46 
47   ndk::SpAIBinder statsServiceBinder =
48       ndk::SpAIBinder(AServiceManager_waitForService(statsServiceName.c_str()));
49   if (statsServiceBinder.get() == nullptr) {
50     LOGE("Failed to get the IStats service binder");
51     return nullptr;
52   }
53 
54   binder_status_t status = AIBinder_linkToDeath(
55       statsServiceBinder.get(), AIBinder_DeathRecipient_new([](void *cookie) {
56         auto *metricsReporter = static_cast<MetricsReporter *>(cookie);
57         metricsReporter->onBinderDied();
58       }),
59       this);
60   if (status != STATUS_OK) {
61     LOGE("Failed to link to death the stats service binder");
62     return nullptr;
63   }
64 
65   std::shared_ptr<IStats> statsService = IStats::fromBinder(statsServiceBinder);
66   if (statsService == nullptr) {
67     LOGE("Failed to get IStats service");
68     return nullptr;
69   }
70   return statsService;
71 }
72 
reportMetric(const VendorAtom & atom)73 bool MetricsReporter::reportMetric(const VendorAtom &atom) {
74   ndk::ScopedAStatus ret;
75   {
76     std::lock_guard<std::mutex> lock(mStatsServiceMutex);
77     if (mStatsService == nullptr) {
78       mStatsService = getStatsService();
79       if (mStatsService == nullptr) {
80         return false;
81       }
82     }
83 
84     ret = mStatsService->reportVendorAtom(atom);
85   }
86 
87   if (!ret.isOk()) {
88     LOGE("Failed to report vendor atom with ID %" PRIi32, atom.atomId);
89   }
90   return ret.isOk();
91 }
92 
logApWakeupOccurred(uint64_t nanoappId)93 bool MetricsReporter::logApWakeupOccurred(uint64_t nanoappId) {
94   std::vector<VendorAtomValue> values(1);
95   values[0].set<VendorAtomValue::longValue>(nanoappId);
96 
97   const VendorAtom atom{
98       .atomId = CHRE_AP_WAKE_UP_OCCURRED,
99       .values{std::move(values)},
100   };
101 
102   return reportMetric(atom);
103 }
104 
logNanoappLoadFailed(uint64_t nanoappId,ChreHalNanoappLoadFailed::Type type,ChreHalNanoappLoadFailed::Reason reason)105 bool MetricsReporter::logNanoappLoadFailed(
106     uint64_t nanoappId, ChreHalNanoappLoadFailed::Type type,
107     ChreHalNanoappLoadFailed::Reason reason) {
108   std::vector<VendorAtomValue> values(3);
109   values[0].set<VendorAtomValue::longValue>(nanoappId);
110   values[1].set<VendorAtomValue::intValue>(type);
111   values[2].set<VendorAtomValue::intValue>(reason);
112 
113   const VendorAtom atom{
114       .atomId = CHRE_HAL_NANOAPP_LOAD_FAILED,
115       .values{std::move(values)},
116   };
117 
118   return reportMetric(atom);
119 }
120 
logPalOpenFailed(ChrePalOpenFailed::ChrePalType pal,ChrePalOpenFailed::Type type)121 bool MetricsReporter::logPalOpenFailed(ChrePalOpenFailed::ChrePalType pal,
122                                        ChrePalOpenFailed::Type type) {
123   std::vector<VendorAtomValue> values(2);
124   values[0].set<VendorAtomValue::intValue>(pal);
125   values[1].set<VendorAtomValue::intValue>(type);
126 
127   const VendorAtom atom{
128       .atomId = CHRE_PAL_OPEN_FAILED,
129       .values{std::move(values)},
130   };
131 
132   return reportMetric(atom);
133 }
134 
logEventQueueSnapshotReported(int32_t snapshotChreGetTimeMs,int32_t maxEventQueueSize,int32_t meanEventQueueSize,int32_t numDroppedEvents)135 bool MetricsReporter::logEventQueueSnapshotReported(
136     int32_t snapshotChreGetTimeMs, int32_t maxEventQueueSize,
137     int32_t meanEventQueueSize, int32_t numDroppedEvents) {
138   std::vector<VendorAtomValue> values(6);
139   values[0].set<VendorAtomValue::intValue>(snapshotChreGetTimeMs);
140   values[1].set<VendorAtomValue::intValue>(maxEventQueueSize);
141   values[2].set<VendorAtomValue::intValue>(meanEventQueueSize);
142   values[3].set<VendorAtomValue::intValue>(numDroppedEvents);
143 
144   // TODO(b/298459533): Implement these two values
145   // Last two values are not currently populated and will be implemented
146   // later. To avoid confusion of the interpretation, we use UINT32_MAX
147   // as a placeholder value.
148   values[4].set<VendorAtomValue::longValue>(
149       std::numeric_limits<int64_t>::max());
150   values[5].set<VendorAtomValue::longValue>(
151       std::numeric_limits<int64_t>::max());
152 
153   const VendorAtom atom{
154       .atomId = CHRE_EVENT_QUEUE_SNAPSHOT_REPORTED,
155       .values{std::move(values)},
156   };
157 
158   return reportMetric(atom);
159 }
160 
onBinderDied()161 void MetricsReporter::onBinderDied() {
162   LOGI("MetricsReporter: stats service died - reconnecting");
163 
164   std::lock_guard<std::mutex> lock(mStatsServiceMutex);
165   mStatsService.reset();
166   mStatsService = getStatsService();
167 }
168 
169 }  // namespace android::chre
170