diff options
author | Justin Klaassen <justinklaassen@google.com> | 2018-04-15 00:41:15 -0400 |
---|---|---|
committer | Justin Klaassen <justinklaassen@google.com> | 2018-04-15 00:41:15 -0400 |
commit | b8042fc9b036db0a6692ca853428fc6ab1e60892 (patch) | |
tree | 82669ea5d75238758e22d379a42baeada526219e /android/os/ServiceManager.java | |
parent | 4d01eeaffaa720e4458a118baa137a11614f00f7 (diff) | |
download | android-28-b8042fc9b036db0a6692ca853428fc6ab1e60892.tar.gz |
Import Android SDK Platform P [4719250]HEADmastermainandroidx-work-releaseandroidx-webkit-releaseandroidx-viewpager2-releaseandroidx-versionedparcelable-releaseandroidx-vectordrawable-releaseandroidx-transition-releaseandroidx-sqlite-releaseandroidx-sharetarget-releaseandroidx-security-security-crypto-releaseandroidx-savedstate-releaseandroidx-room-releaseandroidx-recyclerview-releaseandroidx-recyclerview-recyclerview-selection-releaseandroidx-preference-releaseandroidx-paging-releaseandroidx-paging-legacy-releaseandroidx-navigation-releaseandroidx-mediarouter-releaseandroidx-media2-releaseandroidx-media2-media2-widget-releaseandroidx-media-releaseandroidx-master-releaseandroidx-localbroadcastmanager-releaseandroidx-loader-releaseandroidx-lifecycle-releaseandroidx-jetifier-releaseandroidx-g3-releaseandroidx-fragment-releaseandroidx-exifinterface-releaseandroidx-enterprise-releaseandroidx-core-releaseandroidx-core-core-role-releaseandroidx-coordinatorlayout-releaseandroidx-concurrent-releaseandroidx-compose-releaseandroidx-collection-releaseandroidx-camerax-releaseandroidx-browser-releaseandroidx-biometric-releaseandroidx-benchmark-releaseandroidx-autofill-releaseandroidx-arch-core-releaseandroidx-appcompat-releaseandroidx-annotation-releaseandroidx-annotation-annotation-experimental-releaseandroidx-activity-releaseandroid-arch-work-releaseandroid-arch-navigation-release
/google/data/ro/projects/android/fetch_artifact \
--bid 4719250 \
--target sdk_phone_armv7-win_sdk \
sdk-repo-linux-sources-4719250.zip
AndroidVersion.ApiLevel has been modified to appear as 28
Change-Id: I9ec0a12c9251b8449dba0d86b0cfdbcca16b0a7c
Diffstat (limited to 'android/os/ServiceManager.java')
-rw-r--r-- | android/os/ServiceManager.java | 229 |
1 files changed, 219 insertions, 10 deletions
diff --git a/android/os/ServiceManager.java b/android/os/ServiceManager.java index 34c78455..165276d5 100644 --- a/android/os/ServiceManager.java +++ b/android/os/ServiceManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,98 @@ package android.os; +import android.util.Log; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.os.BinderInternal; +import com.android.internal.util.StatLogger; + +import java.util.HashMap; import java.util.Map; +/** @hide */ public final class ServiceManager { + private static final String TAG = "ServiceManager"; + private static final Object sLock = new Object(); + + private static IServiceManager sServiceManager; + + /** + * Cache for the "well known" services, such as WM and AM. + */ + private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>(); + + /** + * We do the "slow log" at most once every this interval. + */ + private static final int SLOW_LOG_INTERVAL_MS = 5000; + + /** + * We do the "stats log" at most once every this interval. + */ + private static final int STATS_LOG_INTERVAL_MS = 5000; + + /** + * Threshold in uS for a "slow" call, used on core UIDs. We use a more relax value to + * avoid logspam. + */ + private static final long GET_SERVICE_SLOW_THRESHOLD_US_CORE = + SystemProperties.getInt("debug.servicemanager.slow_call_core_ms", 10) * 1000; + + /** + * Threshold in uS for a "slow" call, used on non-core UIDs. We use a more relax value to + * avoid logspam. + */ + private static final long GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE = + SystemProperties.getInt("debug.servicemanager.slow_call_ms", 50) * 1000; + + /** + * We log stats logging ever this many getService() calls. + */ + private static final int GET_SERVICE_LOG_EVERY_CALLS_CORE = + SystemProperties.getInt("debug.servicemanager.log_calls_core", 100); + + /** + * We log stats logging ever this many getService() calls. + */ + private static final int GET_SERVICE_LOG_EVERY_CALLS_NON_CORE = + SystemProperties.getInt("debug.servicemanager.log_calls", 200); + + @GuardedBy("sLock") + private static int sGetServiceAccumulatedUs; + + @GuardedBy("sLock") + private static int sGetServiceAccumulatedCallCount; + + @GuardedBy("sLock") + private static long sLastStatsLogUptime; + + @GuardedBy("sLock") + private static long sLastSlowLogUptime; + + @GuardedBy("sLock") + private static long sLastSlowLogActualTime; + + interface Stats { + int GET_SERVICE = 0; + + int COUNT = GET_SERVICE + 1; + } + + public static final StatLogger sStatLogger = new StatLogger(new String[] { + "getService()", + }); + + private static IServiceManager getIServiceManager() { + if (sServiceManager != null) { + return sServiceManager; + } + + // Find the service manager + sServiceManager = ServiceManagerNative + .asInterface(Binder.allowBlocking(BinderInternal.getContextObject())); + return sServiceManager; + } /** * Returns a reference to a service with the given name. @@ -27,14 +116,32 @@ public final class ServiceManager { * @return a reference to the service, or <code>null</code> if the service doesn't exist */ public static IBinder getService(String name) { + try { + IBinder service = sCache.get(name); + if (service != null) { + return service; + } else { + return Binder.allowBlocking(rawGetService(name)); + } + } catch (RemoteException e) { + Log.e(TAG, "error in getService", e); + } return null; } /** - * Is not supposed to return null, but that is fine for layoutlib. + * Returns a reference to a service with the given name, or throws + * {@link NullPointerException} if none is found. + * + * @hide */ public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException { - throw new ServiceNotFoundException(name); + final IBinder binder = getService(name); + if (binder != null) { + return binder; + } else { + throw new ServiceNotFoundException(name); + } } /** @@ -45,7 +152,39 @@ public final class ServiceManager { * @param service the service object */ public static void addService(String name, IBinder service) { - // pass + addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT); + } + + /** + * Place a new @a service called @a name into the service + * manager. + * + * @param name the name of the new service + * @param service the service object + * @param allowIsolated set to true to allow isolated sandboxed processes + * to access this service + */ + public static void addService(String name, IBinder service, boolean allowIsolated) { + addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT); + } + + /** + * Place a new @a service called @a name into the service + * manager. + * + * @param name the name of the new service + * @param service the service object + * @param allowIsolated set to true to allow isolated sandboxed processes + * @param dumpPriority supported dump priority levels as a bitmask + * to access this service + */ + public static void addService(String name, IBinder service, boolean allowIsolated, + int dumpPriority) { + try { + getIServiceManager().addService(name, service, allowIsolated, dumpPriority); + } catch (RemoteException e) { + Log.e(TAG, "error in addService", e); + } } /** @@ -53,7 +192,17 @@ public final class ServiceManager { * service manager. Non-blocking. */ public static IBinder checkService(String name) { - return null; + try { + IBinder service = sCache.get(name); + if (service != null) { + return service; + } else { + return Binder.allowBlocking(getIServiceManager().checkService(name)); + } + } catch (RemoteException e) { + Log.e(TAG, "error in checkService", e); + return null; + } } /** @@ -62,9 +211,12 @@ public final class ServiceManager { * case of an exception */ public static String[] listServices() { - // actual implementation returns null sometimes, so it's ok - // to return null instead of an empty list. - return null; + try { + return getIServiceManager().listServices(IServiceManager.DUMP_FLAG_PRIORITY_ALL); + } catch (RemoteException e) { + Log.e(TAG, "error in listServices", e); + return null; + } } /** @@ -76,7 +228,10 @@ public final class ServiceManager { * @hide */ public static void initServiceCache(Map<String, IBinder> cache) { - // pass + if (sCache.size() != 0) { + throw new IllegalStateException("setServiceCache may only be called once"); + } + sCache.putAll(cache); } /** @@ -87,9 +242,63 @@ public final class ServiceManager { * @hide */ public static class ServiceNotFoundException extends Exception { - // identical to the original implementation public ServiceNotFoundException(String name) { super("No service published for: " + name); } } + + private static IBinder rawGetService(String name) throws RemoteException { + final long start = sStatLogger.getTime(); + + final IBinder binder = getIServiceManager().getService(name); + + final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start); + + final int myUid = Process.myUid(); + final boolean isCore = UserHandle.isCore(myUid); + + final long slowThreshold = isCore + ? GET_SERVICE_SLOW_THRESHOLD_US_CORE + : GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE; + + synchronized (sLock) { + sGetServiceAccumulatedUs += time; + sGetServiceAccumulatedCallCount++; + + final long nowUptime = SystemClock.uptimeMillis(); + + // Was a slow call? + if (time >= slowThreshold) { + // We do a slow log: + // - At most once in every SLOW_LOG_INTERVAL_MS + // - OR it was slower than the previously logged slow call. + if ((nowUptime > (sLastSlowLogUptime + SLOW_LOG_INTERVAL_MS)) + || (sLastSlowLogActualTime < time)) { + EventLogTags.writeServiceManagerSlow(time / 1000, name); + + sLastSlowLogUptime = nowUptime; + sLastSlowLogActualTime = time; + } + } + + // Every GET_SERVICE_LOG_EVERY_CALLS calls, log the total time spent in getService(). + + final int logInterval = isCore + ? GET_SERVICE_LOG_EVERY_CALLS_CORE + : GET_SERVICE_LOG_EVERY_CALLS_NON_CORE; + + if ((sGetServiceAccumulatedCallCount >= logInterval) + && (nowUptime >= (sLastStatsLogUptime + STATS_LOG_INTERVAL_MS))) { + + EventLogTags.writeServiceManagerStats( + sGetServiceAccumulatedCallCount, // Total # of getService() calls. + sGetServiceAccumulatedUs / 1000, // Total time spent in getService() calls. + (int) (nowUptime - sLastStatsLogUptime)); // Uptime duration since last log. + sGetServiceAccumulatedCallCount = 0; + sGetServiceAccumulatedUs = 0; + sLastStatsLogUptime = nowUptime; + } + } + return binder; + } } |