blob: 95ecf8033f4c631a4a63158bca500ab9583cdc00 [file] [log] [blame]
Bookatzc6977972018-01-16 16:55:05 -08001/*
2 * Copyright (C) 2018 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 // STOPSHIP if true
18#include "Log.h"
19
20#include "SubscriberReporter.h"
21
22using android::IBinder;
23using std::lock_guard;
24using std::unordered_map;
25
26namespace android {
27namespace os {
28namespace statsd {
29
Yao Chen9c1debe2018-02-19 14:39:19 -080030using std::vector;
31
Bookatzc6977972018-01-16 16:55:05 -080032void SubscriberReporter::setBroadcastSubscriber(const ConfigKey& configKey,
33 int64_t subscriberId,
34 const sp<IBinder>& intentSender) {
35 VLOG("SubscriberReporter::setBroadcastSubscriber called.");
36 lock_guard<std::mutex> lock(mLock);
37 mIntentMap[configKey][subscriberId] = intentSender;
38}
39
40void SubscriberReporter::unsetBroadcastSubscriber(const ConfigKey& configKey,
41 int64_t subscriberId) {
42 VLOG("SubscriberReporter::unsetBroadcastSubscriber called.");
43 lock_guard<std::mutex> lock(mLock);
44 auto subscriberMapIt = mIntentMap.find(configKey);
45 if (subscriberMapIt != mIntentMap.end()) {
46 subscriberMapIt->second.erase(subscriberId);
47 if (subscriberMapIt->second.empty()) {
48 mIntentMap.erase(configKey);
49 }
50 }
51}
52
53void SubscriberReporter::removeConfig(const ConfigKey& configKey) {
54 VLOG("SubscriberReporter::removeConfig called.");
55 lock_guard<std::mutex> lock(mLock);
56 mIntentMap.erase(configKey);
57}
58
59void SubscriberReporter::alertBroadcastSubscriber(const ConfigKey& configKey,
60 const Subscription& subscription,
Yangster-mac93694462018-01-22 20:49:31 -080061 const MetricDimensionKey& dimKey) const {
Bookatzc6977972018-01-16 16:55:05 -080062 // Reminder about ids:
63 // subscription id - name of the Subscription (that ties the Alert to the broadcast)
64 // subscription rule_id - the name of the Alert (that triggers the broadcast)
65 // subscriber_id - name of the PendingIntent to use to send the broadcast
66 // config uid - the uid that uploaded the config (and therefore gave the PendingIntent,
67 // although the intent may be to broadcast to a different uid)
68 // config id - the name of this config (for this particular uid)
69
70 VLOG("SubscriberReporter::alertBroadcastSubscriber called.");
71 lock_guard<std::mutex> lock(mLock);
72
73 if (!subscription.has_broadcast_subscriber_details()
74 || !subscription.broadcast_subscriber_details().has_subscriber_id()) {
75 ALOGE("Broadcast subscriber does not have an id.");
76 return;
77 }
78 int64_t subscriberId = subscription.broadcast_subscriber_details().subscriber_id();
79
80 auto it1 = mIntentMap.find(configKey);
81 if (it1 == mIntentMap.end()) {
82 ALOGW("Cannot inform subscriber for missing config key %s ", configKey.ToString().c_str());
83 return;
84 }
85 auto it2 = it1->second.find(subscriberId);
86 if (it2 == it1->second.end()) {
87 ALOGW("Cannot inform subscriber of config %s for missing subscriberId %lld ",
88 configKey.ToString().c_str(), (long long)subscriberId);
89 return;
90 }
91 sendBroadcastLocked(it2->second, configKey, subscription, dimKey);
92}
93
94void SubscriberReporter::sendBroadcastLocked(const sp<IBinder>& intentSender,
95 const ConfigKey& configKey,
96 const Subscription& subscription,
Yangster-mac93694462018-01-22 20:49:31 -080097 const MetricDimensionKey& dimKey) const {
Bookatzc6977972018-01-16 16:55:05 -080098 VLOG("SubscriberReporter::sendBroadcastLocked called.");
99 if (mStatsCompanionService == nullptr) {
100 ALOGW("Failed to send subscriber broadcast: could not access StatsCompanionService.");
101 return;
102 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800103 mStatsCompanionService->sendSubscriberBroadcast(
104 intentSender, configKey.GetUid(), configKey.GetId(), subscription.id(),
105 subscription.rule_id(), getStatsDimensionsValue(dimKey.getDimensionKeyInWhat()));
Bookatzc6977972018-01-16 16:55:05 -0800106}
107
Yao Chen8a8d16c2018-02-08 14:50:40 -0800108void getStatsDimensionsValueHelper(const std::vector<FieldValue>& dims, size_t* index, int depth,
109 int prefix, vector<StatsDimensionsValue>* output) {
110 size_t count = dims.size();
111 while (*index < count) {
112 const auto& dim = dims[*index];
113 const int valueDepth = dim.mField.getDepth();
114 const int valuePrefix = dim.mField.getPrefix(depth);
115 if (valueDepth > 2) {
116 ALOGE("Depth > 2 not supported");
117 return;
118 }
119 if (depth == valueDepth && valuePrefix == prefix) {
120 switch (dim.mValue.getType()) {
121 case INT:
122 output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
123 dim.mValue.int_value));
124 break;
125 case LONG:
126 output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
127 dim.mValue.long_value));
128 break;
129 case FLOAT:
130 output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
131 dim.mValue.float_value));
132 break;
133 case STRING:
134 output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth),
135 String16(dim.mValue.str_value.c_str())));
136 break;
137 default:
138 break;
Bookatzc6977972018-01-16 16:55:05 -0800139 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800140 (*index)++;
141 } else if (valueDepth > depth && valuePrefix == prefix) {
142 vector<StatsDimensionsValue> childOutput;
143 getStatsDimensionsValueHelper(dims, index, depth + 1, dim.mField.getPrefix(depth + 1),
144 &childOutput);
145 output->push_back(StatsDimensionsValue(dim.mField.getPosAtDepth(depth), childOutput));
146 } else {
147 return;
148 }
Bookatzc6977972018-01-16 16:55:05 -0800149 }
150}
151
Yao Chen8a8d16c2018-02-08 14:50:40 -0800152StatsDimensionsValue SubscriberReporter::getStatsDimensionsValue(const HashableDimensionKey& dim) {
153 if (dim.getValues().size() == 0) {
154 return StatsDimensionsValue();
155 }
156
157 vector<StatsDimensionsValue> fields;
158 size_t index = 0;
159 getStatsDimensionsValueHelper(dim.getValues(), &index, 0, 0, &fields);
160 return StatsDimensionsValue(dim.getValues()[0].mField.getTag(), fields);
161}
162
Bookatzc6977972018-01-16 16:55:05 -0800163} // namespace statsd
164} // namespace os
165} // namespace android