blob: e0d085cfaa66cc7892994c26e837ce18e819f292 [file] [log] [blame]
David Chenadaf8b32017-11-03 15:42:08 -07001/*
2 * Copyright 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 */
16package android.util;
17
18import android.Manifest;
19import android.annotation.RequiresPermission;
20import android.annotation.SystemApi;
21import android.os.IBinder;
22import android.os.IStatsManager;
23import android.os.RemoteException;
24import android.os.ServiceManager;
25
26/**
27 * API for StatsD clients to send configurations and retrieve data.
28 *
29 * @hide
30 */
31@SystemApi
32public final class StatsManager {
33 IStatsManager mService;
34 private static final String TAG = "StatsManager";
35
36 /**
37 * Constructor for StatsManagerClient.
38 *
39 * @hide
40 */
41 public StatsManager() {
42 }
43
44 /**
David Chen5914fa02018-01-16 16:38:42 -080045 * Temporary to prevent build failures. Will be deleted.
46 */
47 @RequiresPermission(Manifest.permission.DUMP)
48 public boolean addConfiguration(String configKey, byte[] config, String pkg, String cls) {
49 // To prevent breakages of dependencies on old API.
50
51 return false;
52 }
53
54 /**
David Chenadaf8b32017-11-03 15:42:08 -070055 * Clients can send a configuration and simultaneously registers the name of a broadcast
56 * receiver that listens for when it should request data.
57 *
58 * @param configKey An arbitrary string that allows clients to track the configuration.
59 * @param config Wire-encoded StatsDConfig proto that specifies metrics (and all
60 * dependencies eg, conditions and matchers).
61 * @param pkg The package name to receive the broadcast.
62 * @param cls The name of the class that receives the broadcast.
63 * @return true if successful
64 */
65 @RequiresPermission(Manifest.permission.DUMP)
Yangster-mac94e197c2018-01-02 16:03:03 -080066 public boolean addConfiguration(long configKey, byte[] config, String pkg, String cls) {
David Chenadaf8b32017-11-03 15:42:08 -070067 synchronized (this) {
68 try {
69 IStatsManager service = getIStatsManagerLocked();
70 if (service == null) {
David Chenc562bfb2017-11-17 17:44:33 -080071 Slog.d(TAG, "Failed to find statsd when adding configuration");
72 return false;
David Chenadaf8b32017-11-03 15:42:08 -070073 }
74 return service.addConfiguration(configKey, config, pkg, cls);
75 } catch (RemoteException e) {
David Chenc562bfb2017-11-17 17:44:33 -080076 Slog.d(TAG, "Failed to connect to statsd when adding configuration");
David Chenadaf8b32017-11-03 15:42:08 -070077 return false;
78 }
79 }
80 }
81
82 /**
David Chen5914fa02018-01-16 16:38:42 -080083 * Temporary to prevent build failures. Will be deleted.
84 */
85 @RequiresPermission(Manifest.permission.DUMP)
86 public boolean removeConfiguration(String configKey) {
87 // To prevent breakages of old dependencies.
88 return false;
89 }
90
91 /**
David Chenadaf8b32017-11-03 15:42:08 -070092 * Remove a configuration from logging.
93 *
94 * @param configKey Configuration key to remove.
95 * @return true if successful
96 */
97 @RequiresPermission(Manifest.permission.DUMP)
Yangster-mac94e197c2018-01-02 16:03:03 -080098 public boolean removeConfiguration(long configKey) {
David Chenadaf8b32017-11-03 15:42:08 -070099 synchronized (this) {
100 try {
101 IStatsManager service = getIStatsManagerLocked();
102 if (service == null) {
David Chenc562bfb2017-11-17 17:44:33 -0800103 Slog.d(TAG, "Failed to find statsd when removing configuration");
104 return false;
David Chenadaf8b32017-11-03 15:42:08 -0700105 }
106 return service.removeConfiguration(configKey);
107 } catch (RemoteException e) {
David Chenc562bfb2017-11-17 17:44:33 -0800108 Slog.d(TAG, "Failed to connect to statsd when removing configuration");
David Chenadaf8b32017-11-03 15:42:08 -0700109 return false;
110 }
111 }
112 }
113
114 /**
David Chen5914fa02018-01-16 16:38:42 -0800115 * Temporary to prevent build failures. Will be deleted.
116 */
117 @RequiresPermission(Manifest.permission.DUMP)
118 public byte[] getData(String configKey) {
119 // TODO: remove this and all other methods with String-based config keys.
120 // To prevent build breakages of dependencies.
121 return null;
122 }
123
124 /**
David Chen2e8f3802017-11-22 10:56:48 -0800125 * Clients can request data with a binder call. This getter is destructive and also clears
126 * the retrieved metrics from statsd memory.
David Chenadaf8b32017-11-03 15:42:08 -0700127 *
128 * @param configKey Configuration key to retrieve data from.
David Chen2e8f3802017-11-22 10:56:48 -0800129 * @return Serialized ConfigMetricsReportList proto. Returns null on failure.
David Chenadaf8b32017-11-03 15:42:08 -0700130 */
131 @RequiresPermission(Manifest.permission.DUMP)
Yangster-mac94e197c2018-01-02 16:03:03 -0800132 public byte[] getData(long configKey) {
David Chenadaf8b32017-11-03 15:42:08 -0700133 synchronized (this) {
134 try {
135 IStatsManager service = getIStatsManagerLocked();
136 if (service == null) {
David Chenc562bfb2017-11-17 17:44:33 -0800137 Slog.d(TAG, "Failed to find statsd when getting data");
138 return null;
David Chenadaf8b32017-11-03 15:42:08 -0700139 }
140 return service.getData(configKey);
141 } catch (RemoteException e) {
142 Slog.d(TAG, "Failed to connecto statsd when getting data");
143 return null;
144 }
145 }
146 }
147
David Chen2e8f3802017-11-22 10:56:48 -0800148 /**
149 * Clients can request metadata for statsd. Will contain stats across all configurations but not
150 * the actual metrics themselves (metrics must be collected via {@link #getData(String)}.
151 * This getter is not destructive and will not reset any metrics/counters.
152 *
153 * @return Serialized StatsdStatsReport proto. Returns null on failure.
154 */
155 @RequiresPermission(Manifest.permission.DUMP)
156 public byte[] getMetadata() {
157 synchronized (this) {
158 try {
159 IStatsManager service = getIStatsManagerLocked();
160 if (service == null) {
161 Slog.d(TAG, "Failed to find statsd when getting metadata");
162 return null;
163 }
164 return service.getMetadata();
165 } catch (RemoteException e) {
166 Slog.d(TAG, "Failed to connecto statsd when getting metadata");
167 return null;
168 }
169 }
170 }
171
David Chenadaf8b32017-11-03 15:42:08 -0700172 private class StatsdDeathRecipient implements IBinder.DeathRecipient {
173 @Override
174 public void binderDied() {
175 synchronized (this) {
176 mService = null;
177 }
178 }
179 }
180
181 private IStatsManager getIStatsManagerLocked() throws RemoteException {
182 if (mService != null) {
183 return mService;
184 }
185 mService = IStatsManager.Stub.asInterface(ServiceManager.getService("stats"));
186 if (mService != null) {
187 mService.asBinder().linkToDeath(new StatsdDeathRecipient(), 0);
188 }
189 return mService;
190 }
191}