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