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