blob: 2966bff2ee4cbb89741e95b8688c52b6a7bba9ee [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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
17package android.os;
18
Robert Benea1901a5b2018-05-15 16:36:07 -070019import android.util.ArrayMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.util.Log;
21
Makoto Onuki49392d32018-04-11 13:51:02 -070022import com.android.internal.annotations.GuardedBy;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060023import com.android.internal.os.BinderInternal;
Makoto Onuki49392d32018-04-11 13:51:02 -070024import com.android.internal.util.StatLogger;
Jeff Sharkey49ca5292016-05-10 12:54:45 -060025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import java.util.Map;
27
28/** @hide */
29public final class ServiceManager {
30 private static final String TAG = "ServiceManager";
Makoto Onuki49392d32018-04-11 13:51:02 -070031 private static final Object sLock = new Object();
32
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033 private static IServiceManager sServiceManager;
Makoto Onuki49392d32018-04-11 13:51:02 -070034
35 /**
36 * Cache for the "well known" services, such as WM and AM.
37 */
Robert Benea1901a5b2018-05-15 16:36:07 -070038 private static Map<String, IBinder> sCache = new ArrayMap<String, IBinder>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039
Makoto Onuki49392d32018-04-11 13:51:02 -070040 /**
41 * We do the "slow log" at most once every this interval.
42 */
43 private static final int SLOW_LOG_INTERVAL_MS = 5000;
44
45 /**
46 * We do the "stats log" at most once every this interval.
47 */
48 private static final int STATS_LOG_INTERVAL_MS = 5000;
49
50 /**
51 * Threshold in uS for a "slow" call, used on core UIDs. We use a more relax value to
52 * avoid logspam.
53 */
54 private static final long GET_SERVICE_SLOW_THRESHOLD_US_CORE =
55 SystemProperties.getInt("debug.servicemanager.slow_call_core_ms", 10) * 1000;
56
57 /**
58 * Threshold in uS for a "slow" call, used on non-core UIDs. We use a more relax value to
59 * avoid logspam.
60 */
61 private static final long GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE =
62 SystemProperties.getInt("debug.servicemanager.slow_call_ms", 50) * 1000;
63
64 /**
65 * We log stats logging ever this many getService() calls.
66 */
67 private static final int GET_SERVICE_LOG_EVERY_CALLS_CORE =
68 SystemProperties.getInt("debug.servicemanager.log_calls_core", 100);
69
70 /**
71 * We log stats logging ever this many getService() calls.
72 */
73 private static final int GET_SERVICE_LOG_EVERY_CALLS_NON_CORE =
74 SystemProperties.getInt("debug.servicemanager.log_calls", 200);
75
76 @GuardedBy("sLock")
77 private static int sGetServiceAccumulatedUs;
78
79 @GuardedBy("sLock")
80 private static int sGetServiceAccumulatedCallCount;
81
82 @GuardedBy("sLock")
83 private static long sLastStatsLogUptime;
84
85 @GuardedBy("sLock")
86 private static long sLastSlowLogUptime;
87
88 @GuardedBy("sLock")
89 private static long sLastSlowLogActualTime;
90
91 interface Stats {
92 int GET_SERVICE = 0;
93
94 int COUNT = GET_SERVICE + 1;
95 }
96
97 public static final StatLogger sStatLogger = new StatLogger(new String[] {
98 "getService()",
99 });
100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 private static IServiceManager getIServiceManager() {
102 if (sServiceManager != null) {
103 return sServiceManager;
104 }
105
106 // Find the service manager
Jeff Sharkey0a17db12016-11-04 11:23:46 -0600107 sServiceManager = ServiceManagerNative
108 .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 return sServiceManager;
110 }
111
112 /**
113 * Returns a reference to a service with the given name.
Vishnu Nair05768192017-09-19 15:25:38 -0700114 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 * @param name the name of the service to get
116 * @return a reference to the service, or <code>null</code> if the service doesn't exist
117 */
118 public static IBinder getService(String name) {
119 try {
120 IBinder service = sCache.get(name);
121 if (service != null) {
122 return service;
123 } else {
Makoto Onuki49392d32018-04-11 13:51:02 -0700124 return Binder.allowBlocking(rawGetService(name));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 }
126 } catch (RemoteException e) {
127 Log.e(TAG, "error in getService", e);
128 }
129 return null;
130 }
131
132 /**
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600133 * Returns a reference to a service with the given name, or throws
134 * {@link NullPointerException} if none is found.
135 *
136 * @hide
137 */
138 public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
139 final IBinder binder = getService(name);
140 if (binder != null) {
141 return binder;
142 } else {
143 throw new ServiceNotFoundException(name);
144 }
145 }
146
147 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 * Place a new @a service called @a name into the service
149 * manager.
Vishnu Nair05768192017-09-19 15:25:38 -0700150 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 * @param name the name of the new service
152 * @param service the service object
153 */
154 public static void addService(String name, IBinder service) {
Vishnu Nairdf6c6e72018-02-01 15:14:44 -0800155 addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
Dianne Hackborna573f6a2012-02-09 16:12:18 -0800156 }
157
158 /**
159 * Place a new @a service called @a name into the service
160 * manager.
Vishnu Nair05768192017-09-19 15:25:38 -0700161 *
Dianne Hackborna573f6a2012-02-09 16:12:18 -0800162 * @param name the name of the new service
163 * @param service the service object
164 * @param allowIsolated set to true to allow isolated sandboxed processes
165 * to access this service
166 */
167 public static void addService(String name, IBinder service, boolean allowIsolated) {
Vishnu Nairdf6c6e72018-02-01 15:14:44 -0800168 addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
Vishnu Nair05768192017-09-19 15:25:38 -0700169 }
170
171 /**
172 * Place a new @a service called @a name into the service
173 * manager.
174 *
175 * @param name the name of the new service
176 * @param service the service object
177 * @param allowIsolated set to true to allow isolated sandboxed processes
178 * @param dumpPriority supported dump priority levels as a bitmask
179 * to access this service
180 */
181 public static void addService(String name, IBinder service, boolean allowIsolated,
182 int dumpPriority) {
Dianne Hackborna573f6a2012-02-09 16:12:18 -0800183 try {
Vishnu Nair05768192017-09-19 15:25:38 -0700184 getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 } catch (RemoteException e) {
186 Log.e(TAG, "error in addService", e);
187 }
188 }
Vishnu Nair05768192017-09-19 15:25:38 -0700189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 /**
191 * Retrieve an existing service called @a name from the
192 * service manager. Non-blocking.
193 */
194 public static IBinder checkService(String name) {
195 try {
196 IBinder service = sCache.get(name);
197 if (service != null) {
198 return service;
199 } else {
Jeff Sharkey0a17db12016-11-04 11:23:46 -0600200 return Binder.allowBlocking(getIServiceManager().checkService(name));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 }
202 } catch (RemoteException e) {
203 Log.e(TAG, "error in checkService", e);
204 return null;
205 }
206 }
207
208 /**
209 * Return a list of all currently running services.
Umair Khan9ccebbf2016-01-06 19:47:20 +0530210 * @return an array of all currently running services, or <code>null</code> in
211 * case of an exception
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 */
Umair Khan9ccebbf2016-01-06 19:47:20 +0530213 public static String[] listServices() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 try {
Vishnu Naire78b01a2017-10-26 10:11:54 -0700215 return getIServiceManager().listServices(IServiceManager.DUMP_FLAG_PRIORITY_ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 } catch (RemoteException e) {
217 Log.e(TAG, "error in listServices", e);
218 return null;
219 }
220 }
221
222 /**
223 * This is only intended to be called when the process is first being brought
224 * up and bound by the activity manager. There is only one thread in the process
225 * at that time, so no locking is done.
Vishnu Nair05768192017-09-19 15:25:38 -0700226 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 * @param cache the cache of service references
228 * @hide
229 */
230 public static void initServiceCache(Map<String, IBinder> cache) {
Jeff Brown10e89712011-07-08 18:52:57 -0700231 if (sCache.size() != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 throw new IllegalStateException("setServiceCache may only be called once");
233 }
234 sCache.putAll(cache);
235 }
Jeff Sharkey49ca5292016-05-10 12:54:45 -0600236
237 /**
238 * Exception thrown when no service published for given name. This might be
239 * thrown early during boot before certain services have published
240 * themselves.
241 *
242 * @hide
243 */
244 public static class ServiceNotFoundException extends Exception {
245 public ServiceNotFoundException(String name) {
246 super("No service published for: " + name);
247 }
248 }
Makoto Onuki49392d32018-04-11 13:51:02 -0700249
250 private static IBinder rawGetService(String name) throws RemoteException {
251 final long start = sStatLogger.getTime();
252
253 final IBinder binder = getIServiceManager().getService(name);
254
255 final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start);
256
257 final int myUid = Process.myUid();
258 final boolean isCore = UserHandle.isCore(myUid);
259
260 final long slowThreshold = isCore
261 ? GET_SERVICE_SLOW_THRESHOLD_US_CORE
262 : GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE;
263
264 synchronized (sLock) {
265 sGetServiceAccumulatedUs += time;
266 sGetServiceAccumulatedCallCount++;
267
268 final long nowUptime = SystemClock.uptimeMillis();
269
270 // Was a slow call?
271 if (time >= slowThreshold) {
272 // We do a slow log:
273 // - At most once in every SLOW_LOG_INTERVAL_MS
274 // - OR it was slower than the previously logged slow call.
275 if ((nowUptime > (sLastSlowLogUptime + SLOW_LOG_INTERVAL_MS))
276 || (sLastSlowLogActualTime < time)) {
277 EventLogTags.writeServiceManagerSlow(time / 1000, name);
278
279 sLastSlowLogUptime = nowUptime;
280 sLastSlowLogActualTime = time;
281 }
282 }
283
284 // Every GET_SERVICE_LOG_EVERY_CALLS calls, log the total time spent in getService().
285
286 final int logInterval = isCore
287 ? GET_SERVICE_LOG_EVERY_CALLS_CORE
288 : GET_SERVICE_LOG_EVERY_CALLS_NON_CORE;
289
290 if ((sGetServiceAccumulatedCallCount >= logInterval)
291 && (nowUptime >= (sLastStatsLogUptime + STATS_LOG_INTERVAL_MS))) {
292
293 EventLogTags.writeServiceManagerStats(
294 sGetServiceAccumulatedCallCount, // Total # of getService() calls.
295 sGetServiceAccumulatedUs / 1000, // Total time spent in getService() calls.
296 (int) (nowUptime - sLastStatsLogUptime)); // Uptime duration since last log.
297 sGetServiceAccumulatedCallCount = 0;
298 sGetServiceAccumulatedUs = 0;
299 sLastStatsLogUptime = nowUptime;
300 }
301 }
302 return binder;
303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304}