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