1 /*
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 
17 package android.os;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.compat.annotation.UnsupportedAppUsage;
23 import android.util.ArrayMap;
24 import android.util.Log;
25 
26 import com.android.internal.annotations.GuardedBy;
27 import com.android.internal.os.BinderInternal;
28 import com.android.internal.util.StatLogger;
29 
30 import java.util.Map;
31 
32 /**
33  * Manage binder services as registered with the binder context manager. These services must be
34  * declared statically on an Android device (SELinux access_vector service_manager, w/ service
35  * names in service_contexts files), and they do not follow the activity lifecycle. When
36  * building applications, android.app.Service should be preferred.
37  *
38  * @hide
39  **/
40 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
41 public final class ServiceManager {
42     private static final String TAG = "ServiceManager";
43     private static final Object sLock = new Object();
44 
45     @UnsupportedAppUsage
46     private static IServiceManager sServiceManager;
47 
48     /**
49      * Cache for the "well known" services, such as WM and AM.
50      */
51     @UnsupportedAppUsage
52     private static Map<String, IBinder> sCache = new ArrayMap<String, IBinder>();
53 
54     /**
55      * We do the "slow log" at most once every this interval.
56      */
57     private static final int SLOW_LOG_INTERVAL_MS = 5000;
58 
59     /**
60      * We do the "stats log" at most once every this interval.
61      */
62     private static final int STATS_LOG_INTERVAL_MS = 5000;
63 
64     /**
65      * Threshold in uS for a "slow" call, used on core UIDs. We use a more relax value to
66      * avoid logspam.
67      */
68     private static final long GET_SERVICE_SLOW_THRESHOLD_US_CORE =
69             SystemProperties.getInt("debug.servicemanager.slow_call_core_ms", 10) * 1000;
70 
71     /**
72      * Threshold in uS for a "slow" call, used on non-core UIDs. We use a more relax value to
73      * avoid logspam.
74      */
75     private static final long GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE =
76             SystemProperties.getInt("debug.servicemanager.slow_call_ms", 50) * 1000;
77 
78     /**
79      * We log stats logging ever this many getService() calls.
80      */
81     private static final int GET_SERVICE_LOG_EVERY_CALLS_CORE =
82             SystemProperties.getInt("debug.servicemanager.log_calls_core", 100);
83 
84     /**
85      * We log stats logging ever this many getService() calls.
86      */
87     private static final int GET_SERVICE_LOG_EVERY_CALLS_NON_CORE =
88             SystemProperties.getInt("debug.servicemanager.log_calls", 200);
89 
90     @GuardedBy("sLock")
91     private static int sGetServiceAccumulatedUs;
92 
93     @GuardedBy("sLock")
94     private static int sGetServiceAccumulatedCallCount;
95 
96     @GuardedBy("sLock")
97     private static long sLastStatsLogUptime;
98 
99     @GuardedBy("sLock")
100     private static long sLastSlowLogUptime;
101 
102     @GuardedBy("sLock")
103     private static long sLastSlowLogActualTime;
104 
105     interface Stats {
106         int GET_SERVICE = 0;
107 
108         int COUNT = GET_SERVICE + 1;
109     }
110 
111     /** @hide */
112     public static final StatLogger sStatLogger = new StatLogger(new String[] {
113             "getService()",
114     });
115 
116     /** @hide */
117     @UnsupportedAppUsage
ServiceManager()118     public ServiceManager() {
119     }
120 
121     @UnsupportedAppUsage
getIServiceManager()122     private static IServiceManager getIServiceManager() {
123         if (sServiceManager != null) {
124             return sServiceManager;
125         }
126 
127         // Find the service manager
128         sServiceManager = ServiceManagerNative
129                 .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
130         return sServiceManager;
131     }
132 
133     /**
134      * Returns a reference to a service with the given name.
135      *
136      * @param name the name of the service to get
137      * @return a reference to the service, or <code>null</code> if the service doesn't exist
138      * @hide
139      */
140     @UnsupportedAppUsage
getService(String name)141     public static IBinder getService(String name) {
142         try {
143             IBinder service = sCache.get(name);
144             if (service != null) {
145                 return service;
146             } else {
147                 return Binder.allowBlocking(rawGetService(name));
148             }
149         } catch (RemoteException e) {
150             Log.e(TAG, "error in getService", e);
151         }
152         return null;
153     }
154 
155     /**
156      * Returns a reference to a service with the given name, or throws
157      * {@link ServiceNotFoundException} if none is found.
158      *
159      * @hide
160      */
getServiceOrThrow(String name)161     public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
162         final IBinder binder = getService(name);
163         if (binder != null) {
164             return binder;
165         } else {
166             throw new ServiceNotFoundException(name);
167         }
168     }
169 
170     /**
171      * Place a new @a service called @a name into the service
172      * manager.
173      *
174      * @param name the name of the new service
175      * @param service the service object
176      * @hide
177      */
178     @UnsupportedAppUsage
addService(String name, IBinder service)179     public static void addService(String name, IBinder service) {
180         addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
181     }
182 
183     /**
184      * Place a new @a service called @a name into the service
185      * manager.
186      *
187      * @param name the name of the new service
188      * @param service the service object
189      * @param allowIsolated set to true to allow isolated sandboxed processes
190      * to access this service
191      * @hide
192      */
193     @UnsupportedAppUsage
addService(String name, IBinder service, boolean allowIsolated)194     public static void addService(String name, IBinder service, boolean allowIsolated) {
195         addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
196     }
197 
198     /**
199      * Place a new @a service called @a name into the service
200      * manager.
201      *
202      * @param name the name of the new service
203      * @param service the service object
204      * @param allowIsolated set to true to allow isolated sandboxed processes
205      * @param dumpPriority supported dump priority levels as a bitmask
206      * to access this service
207      * @hide
208      */
209     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)210     public static void addService(String name, IBinder service, boolean allowIsolated,
211             int dumpPriority) {
212         try {
213             getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
214         } catch (RemoteException e) {
215             Log.e(TAG, "error in addService", e);
216         }
217     }
218 
219     /**
220      * Retrieve an existing service called @a name from the
221      * service manager.  Non-blocking.
222      * @hide
223      */
224     @UnsupportedAppUsage
checkService(String name)225     public static IBinder checkService(String name) {
226         try {
227             IBinder service = sCache.get(name);
228             if (service != null) {
229                 return service;
230             } else {
231                 return Binder.allowBlocking(getIServiceManager().checkService(name));
232             }
233         } catch (RemoteException e) {
234             Log.e(TAG, "error in checkService", e);
235             return null;
236         }
237     }
238 
239     /**
240      * Returns whether the specified service is declared.
241      *
242      * @return true if the service is declared somewhere (eg. VINTF manifest) and
243      * waitForService should always be able to return the service.
244      */
isDeclared(@onNull String name)245     public static boolean isDeclared(@NonNull String name) {
246         try {
247             return getIServiceManager().isDeclared(name);
248         } catch (RemoteException e) {
249             Log.e(TAG, "error in isDeclared", e);
250             return false;
251         }
252     }
253 
254     /**
255      * Returns an array of all declared instances for a particular interface.
256      *
257      * For instance, if 'android.foo.IFoo/foo' is declared (e.g. in VINTF
258      * manifest), and 'android.foo.IFoo' is passed here, then ["foo"] would be
259      * returned.
260      *
261      * @hide
262      */
263     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
264     @NonNull
getDeclaredInstances(@onNull String iface)265     public static String[] getDeclaredInstances(@NonNull String iface) {
266         try {
267             return getIServiceManager().getDeclaredInstances(iface);
268         } catch (RemoteException e) {
269             Log.e(TAG, "error in getDeclaredInstances", e);
270             throw e.rethrowFromSystemServer();
271         }
272     }
273 
274     /**
275      * Returns the specified service from the service manager.
276      *
277      * If the service is not running, servicemanager will attempt to start it, and this function
278      * will wait for it to be ready.
279      *
280      * @return {@code null} only if there are permission problems or fatal errors.
281      * @hide
282      */
waitForService(@onNull String name)283     public static IBinder waitForService(@NonNull String name) {
284         return Binder.allowBlocking(waitForServiceNative(name));
285     }
286 
waitForServiceNative(@onNull String name)287     private static native IBinder waitForServiceNative(@NonNull String name);
288 
289     /**
290      * Returns the specified service from the service manager, if declared.
291      *
292      * If the service is not running, servicemanager will attempt to start it, and this function
293      * will wait for it to be ready.
294      *
295      * @throws SecurityException if the process does not have the permissions to check
296      * isDeclared() for the service.
297      * @return {@code null} if the service is not declared in the manifest, or if there
298      * are fatal errors.
299      * @hide
300      */
301     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
waitForDeclaredService(@onNull String name)302     @Nullable public static IBinder waitForDeclaredService(@NonNull String name) {
303         return isDeclared(name) ? waitForService(name) : null;
304     }
305 
306     /**
307      * Register callback for service registration notifications.
308      *
309      * @throws RemoteException for underlying error.
310      * @hide
311      */
registerForNotifications( @onNull String name, @NonNull IServiceCallback callback)312     public static void registerForNotifications(
313             @NonNull String name, @NonNull IServiceCallback callback) throws RemoteException {
314         getIServiceManager().registerForNotifications(name, callback);
315     }
316 
317     /**
318      * Return a list of all currently running services.
319      * @return an array of all currently running services, or <code>null</code> in
320      * case of an exception
321      * @hide
322      */
323     @UnsupportedAppUsage
listServices()324     public static String[] listServices() {
325         try {
326             return getIServiceManager().listServices(IServiceManager.DUMP_FLAG_PRIORITY_ALL);
327         } catch (RemoteException e) {
328             Log.e(TAG, "error in listServices", e);
329             return null;
330         }
331     }
332 
333     /**
334      * Get service debug info.
335      * @return an array of information for each service (like listServices, but with PIDs)
336      * @hide
337      */
getServiceDebugInfo()338     public static ServiceDebugInfo[] getServiceDebugInfo() {
339         try {
340             return getIServiceManager().getServiceDebugInfo();
341         } catch (RemoteException e) {
342             Log.e(TAG, "error in getServiceDebugInfo", e);
343             return null;
344         }
345     }
346 
347     /**
348      * This is only intended to be called when the process is first being brought
349      * up and bound by the activity manager. There is only one thread in the process
350      * at that time, so no locking is done.
351      *
352      * @param cache the cache of service references
353      * @hide
354      */
initServiceCache(Map<String, IBinder> cache)355     public static void initServiceCache(Map<String, IBinder> cache) {
356         if (sCache.size() != 0) {
357             throw new IllegalStateException("setServiceCache may only be called once");
358         }
359         sCache.putAll(cache);
360     }
361 
362     /**
363      * Exception thrown when no service published for given name. This might be
364      * thrown early during boot before certain services have published
365      * themselves.
366      *
367      * @hide
368      */
369     public static class ServiceNotFoundException extends Exception {
ServiceNotFoundException(String name)370         public ServiceNotFoundException(String name) {
371             super("No service published for: " + name);
372         }
373     }
374 
rawGetService(String name)375     private static IBinder rawGetService(String name) throws RemoteException {
376         final long start = sStatLogger.getTime();
377 
378         final IBinder binder = getIServiceManager().getService(name);
379 
380         final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start);
381 
382         final int myUid = Process.myUid();
383         final boolean isCore = UserHandle.isCore(myUid);
384 
385         final long slowThreshold = isCore
386                 ? GET_SERVICE_SLOW_THRESHOLD_US_CORE
387                 : GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE;
388 
389         synchronized (sLock) {
390             sGetServiceAccumulatedUs += time;
391             sGetServiceAccumulatedCallCount++;
392 
393             final long nowUptime = SystemClock.uptimeMillis();
394 
395             // Was a slow call?
396             if (time >= slowThreshold) {
397                 // We do a slow log:
398                 // - At most once in every SLOW_LOG_INTERVAL_MS
399                 // - OR it was slower than the previously logged slow call.
400                 if ((nowUptime > (sLastSlowLogUptime + SLOW_LOG_INTERVAL_MS))
401                         || (sLastSlowLogActualTime < time)) {
402                     EventLogTags.writeServiceManagerSlow(time / 1000, name);
403 
404                     sLastSlowLogUptime = nowUptime;
405                     sLastSlowLogActualTime = time;
406                 }
407             }
408 
409             // Every GET_SERVICE_LOG_EVERY_CALLS calls, log the total time spent in getService().
410 
411             final int logInterval = isCore
412                     ? GET_SERVICE_LOG_EVERY_CALLS_CORE
413                     : GET_SERVICE_LOG_EVERY_CALLS_NON_CORE;
414 
415             if ((sGetServiceAccumulatedCallCount >= logInterval)
416                     && (nowUptime >= (sLastStatsLogUptime + STATS_LOG_INTERVAL_MS))) {
417 
418                 EventLogTags.writeServiceManagerStats(
419                         sGetServiceAccumulatedCallCount, // Total # of getService() calls.
420                         sGetServiceAccumulatedUs / 1000, // Total time spent in getService() calls.
421                         (int) (nowUptime - sLastStatsLogUptime)); // Uptime duration since last log.
422                 sGetServiceAccumulatedCallCount = 0;
423                 sGetServiceAccumulatedUs = 0;
424                 sLastStatsLogUptime = nowUptime;
425             }
426         }
427         return binder;
428     }
429 }
430