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 #pragma once
18 
19 #include <android/os/IStatsCompanionService.h>
20 #include <utils/RefBase.h>
21 
22 #include "config/ConfigKey.h"
23 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"  // subscription
24 #include "android/os/StatsDimensionsValue.h"
25 #include "HashableDimensionKey.h"
26 
27 #include <mutex>
28 #include <unordered_map>
29 #include <vector>
30 
31 namespace android {
32 namespace os {
33 namespace statsd {
34 
35 // Reports information to subscribers.
36 // Single instance shared across the process. All methods are thread safe.
37 class SubscriberReporter {
38 public:
39     /** Get (singleton) instance of SubscriberReporter. */
getInstance()40     static SubscriberReporter& getInstance() {
41         static SubscriberReporter subscriberReporter;
42         return subscriberReporter;
43     }
44 
~SubscriberReporter()45     ~SubscriberReporter(){};
46     SubscriberReporter(SubscriberReporter const&) = delete;
47     void operator=(SubscriberReporter const&) = delete;
48 
49     /**
50      * Tells SubscriberReporter what IStatsCompanionService to use.
51      * May be nullptr, but SubscriberReporter will not send broadcasts for any calls
52      * to alertBroadcastSubscriber that occur while nullptr.
53      */
setStatsCompanionService(sp<IStatsCompanionService> statsCompanionService)54     void setStatsCompanionService(sp<IStatsCompanionService> statsCompanionService) {
55         std::lock_guard<std::mutex> lock(mLock);
56         sp<IStatsCompanionService> tmpForLock = mStatsCompanionService;
57         mStatsCompanionService = statsCompanionService;
58     }
59 
60     /**
61      * Stores the given intentSender, associating it with the given (configKey, subscriberId) pair.
62      * intentSender must be convertible into an IntentSender (in Java) using IntentSender(IBinder).
63      */
64     void setBroadcastSubscriber(const ConfigKey& configKey,
65                                 int64_t subscriberId,
66                                 const sp<android::IBinder>& intentSender);
67 
68     /**
69      * Erases any intentSender information from the given (configKey, subscriberId) pair.
70      */
71     void unsetBroadcastSubscriber(const ConfigKey& configKey, int64_t subscriberId);
72 
73     /** Remove all information stored by SubscriberReporter about the given config. */
74     void removeConfig(const ConfigKey& configKey);
75 
76     /**
77      * Sends a broadcast via the intentSender previously stored for the
78      * given (configKey, subscriberId) pair by setBroadcastSubscriber.
79      * Information about the subscriber, as well as information extracted from the dimKey, is sent.
80      */
81     void alertBroadcastSubscriber(const ConfigKey& configKey,
82                                   const Subscription& subscription,
83                                   const MetricDimensionKey& dimKey) const;
84 
85     static StatsDimensionsValue getStatsDimensionsValue(const HashableDimensionKey& dim);
86 
87 private:
SubscriberReporter()88     SubscriberReporter() {};
89 
90     mutable std::mutex mLock;
91 
92     /** Binder interface for communicating with StatsCompanionService. */
93     sp<IStatsCompanionService> mStatsCompanionService = nullptr;
94 
95     /** Maps <ConfigKey, SubscriberId> -> IBinder (which represents an IIntentSender). */
96     std::unordered_map<ConfigKey,
97             std::unordered_map<int64_t, sp<android::IBinder>>> mIntentMap;
98 
99     /**
100      * Sends a broadcast via the given intentSender (using mStatsCompanionService), along
101      * with the information in the other parameters.
102      */
103     void sendBroadcastLocked(const sp<android::IBinder>& intentSender,
104                              const ConfigKey& configKey,
105                              const Subscription& subscription,
106                              const std::vector<String16>& cookies,
107                              const MetricDimensionKey& dimKey) const;
108 };
109 
110 }  // namespace statsd
111 }  // namespace os
112 }  // namespace android
113