Bookatz | c697797 | 2018-01-16 16:55:05 -0800 | [diff] [blame] | 1 | /* |
| 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 | |
| 22 | using android::IBinder; |
| 23 | using std::lock_guard; |
| 24 | using std::unordered_map; |
| 25 | |
| 26 | namespace android { |
| 27 | namespace os { |
| 28 | namespace statsd { |
| 29 | |
Yao Chen | 9c1debe | 2018-02-19 14:39:19 -0800 | [diff] [blame] | 30 | using std::vector; |
| 31 | |
Bookatz | c697797 | 2018-01-16 16:55:05 -0800 | [diff] [blame] | 32 | void 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 | |
| 40 | void 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 | |
| 53 | void SubscriberReporter::removeConfig(const ConfigKey& configKey) { |
| 54 | VLOG("SubscriberReporter::removeConfig called."); |
| 55 | lock_guard<std::mutex> lock(mLock); |
| 56 | mIntentMap.erase(configKey); |
| 57 | } |
| 58 | |
| 59 | void SubscriberReporter::alertBroadcastSubscriber(const ConfigKey& configKey, |
| 60 | const Subscription& subscription, |
Yangster-mac | 9369446 | 2018-01-22 20:49:31 -0800 | [diff] [blame] | 61 | const MetricDimensionKey& dimKey) const { |
Bookatz | c697797 | 2018-01-16 16:55:05 -0800 | [diff] [blame] | 62 | // 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 | |
| 94 | void SubscriberReporter::sendBroadcastLocked(const sp<IBinder>& intentSender, |
| 95 | const ConfigKey& configKey, |
| 96 | const Subscription& subscription, |
Yangster-mac | 9369446 | 2018-01-22 20:49:31 -0800 | [diff] [blame] | 97 | const MetricDimensionKey& dimKey) const { |
Bookatz | c697797 | 2018-01-16 16:55:05 -0800 | [diff] [blame] | 98 | VLOG("SubscriberReporter::sendBroadcastLocked called."); |
| 99 | if (mStatsCompanionService == nullptr) { |
| 100 | ALOGW("Failed to send subscriber broadcast: could not access StatsCompanionService."); |
| 101 | return; |
| 102 | } |
Yao Chen | 8a8d16c | 2018-02-08 14:50:40 -0800 | [diff] [blame] | 103 | mStatsCompanionService->sendSubscriberBroadcast( |
| 104 | intentSender, configKey.GetUid(), configKey.GetId(), subscription.id(), |
| 105 | subscription.rule_id(), getStatsDimensionsValue(dimKey.getDimensionKeyInWhat())); |
Bookatz | c697797 | 2018-01-16 16:55:05 -0800 | [diff] [blame] | 106 | } |
| 107 | |
Yao Chen | 8a8d16c | 2018-02-08 14:50:40 -0800 | [diff] [blame] | 108 | void 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; |
Bookatz | c697797 | 2018-01-16 16:55:05 -0800 | [diff] [blame] | 139 | } |
Yao Chen | 8a8d16c | 2018-02-08 14:50:40 -0800 | [diff] [blame] | 140 | (*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 | } |
Bookatz | c697797 | 2018-01-16 16:55:05 -0800 | [diff] [blame] | 149 | } |
| 150 | } |
| 151 | |
Yao Chen | 8a8d16c | 2018-02-08 14:50:40 -0800 | [diff] [blame] | 152 | StatsDimensionsValue 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 | |
Bookatz | c697797 | 2018-01-16 16:55:05 -0800 | [diff] [blame] | 163 | } // namespace statsd |
| 164 | } // namespace os |
| 165 | } // namespace android |