• Android系统服务与服务注册


    一、服务

      

      系统服务将服务注册在ServiceManager中,Client通过ServiceManager获取服务的Bindler实例,通过Binder与服务通信。

      ServiceManager源码(framework/base/core/java/android/os/ServiceManager.java):

    /*
     * 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.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package android.os;
    
    import android.annotation.NonNull;
    import android.compat.annotation.UnsupportedAppUsage;
    import android.util.ArrayMap;
    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.Map;
    
    /** @hide */
    public final class ServiceManager {
        private static final String TAG = "ServiceManager";
        private static final Object sLock = new Object();
    
        @UnsupportedAppUsage
        private static IServiceManager sServiceManager;
    
        /**
         * Cache for the "well known" services, such as WM and AM.
         */
        @UnsupportedAppUsage
        private static Map<String, IBinder> sCache = new ArrayMap<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()",
        });
    
        @UnsupportedAppUsage
        public ServiceManager() {
        }
    
        @UnsupportedAppUsage
        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.
         *
         * @param name the name of the service to get
         * @return a reference to the service, or <code>null</code> if the service doesn't exist
         */
        @UnsupportedAppUsage
        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;
        }
    
        /**
         * Returns a reference to a service with the given name, or throws
         * {@link ServiceNotFoundException} if none is found.
         *
         * @hide
         */
        public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
            final IBinder binder = getService(name);
            if (binder != null) {
                return binder;
            } else {
                throw new ServiceNotFoundException(name);
            }
        }
    
        /**
         * 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
         */
        @UnsupportedAppUsage
        public static void addService(String name, IBinder service) {
            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
         */
        @UnsupportedAppUsage
        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
         */
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        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);
            }
        }
    
        /**
         * Retrieve an existing service called @a name from the
         * service manager.  Non-blocking.
         */
        @UnsupportedAppUsage
        public static IBinder checkService(String name) {
            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;
            }
        }
    
        /**
         * Returns whether the specified service is declared.
         *
         * @return true if the service is declared somewhere (eg. VINTF manifest) and
         * waitForService should always be able to return the service.
         */
        public static boolean isDeclared(@NonNull String name) {
            try {
                return getIServiceManager().isDeclared(name);
            } catch (RemoteException e) {
                Log.e(TAG, "error in isDeclared", e);
                return false;
            }
        }
    
        /**
         * Returns the list of declared instances for an interface.
         *
         * @return true if the service is declared somewhere (eg. VINTF manifest) and
         * waitForService should always be able to return the service.
         */
        public static String[] getDeclaredInstances(@NonNull String iface) {
            try {
                return getIServiceManager().getDeclaredInstances(iface);
            } catch (RemoteException e) {
                Log.e(TAG, "error in getDeclaredInstances", e);
                return null;
            }
        }
    
        /**
         * Returns the specified service from the service manager.
         *
         * If the service is not running, servicemanager will attempt to start it, and this function
         * will wait for it to be ready.
         *
         * @return {@code null} only if there are permission problems or fatal errors.
         */
        public static IBinder waitForService(@NonNull String name) {
            return Binder.allowBlocking(waitForServiceNative(name));
        }
    
        private static native IBinder waitForServiceNative(@NonNull String name);
    
    
        /**
         * Returns the specified service from the service manager, if declared.
         *
         * If the service is not running, servicemanager will attempt to start it, and this function
         * will wait for it to be ready.
         *
         * @return {@code null} if the service is not declared in the manifest, or if there are
         * permission problems, or if there are fatal errors.
         */
        public static IBinder waitForDeclaredService(@NonNull String name) {
            return isDeclared(name) ? waitForService(name) : null;
        }
    
        /**
         * Return a list of all currently running services.
         * @return an array of all currently running services, or <code>null</code> in
         * case of an exception
         */
        @UnsupportedAppUsage
        public static String[] listServices() {
            try {
                return getIServiceManager().listServices(IServiceManager.DUMP_FLAG_PRIORITY_ALL);
            } catch (RemoteException e) {
                Log.e(TAG, "error in listServices", e);
                return null;
            }
        }
    
        /**
         * Get service debug info.
         * @return an array of information for each service (like listServices, but with PIDs)
         * @hide
         */
        public static ServiceDebugInfo[] getServiceDebugInfo() {
            try {
                return getIServiceManager().getServiceDebugInfo();
            } catch (RemoteException e) {
                Log.e(TAG, "error in getServiceDebugInfo", e);
                return null;
            }
        }
    
        /**
         * This is only intended to be called when the process is first being brought
         * up and bound by the activity manager. There is only one thread in the process
         * at that time, so no locking is done.
         *
         * @param cache the cache of service references
         * @hide
         */
        public static void initServiceCache(Map<String, IBinder> cache) {
            if (sCache.size() != 0) {
                throw new IllegalStateException("setServiceCache may only be called once");
            }
            sCache.putAll(cache);
        }
    
        /**
         * Exception thrown when no service published for given name. This might be
         * thrown early during boot before certain services have published
         * themselves.
         *
         * @hide
         */
        public static class ServiceNotFoundException extends Exception {
            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;
        }
    }

    二、如何获取使用系统服务

    /**
       * Cache for the "well known" services, such as WM and AM.
       */
    @UnsupportedAppUsage
    private static Map<String, IBinder> sCache = new ArrayMap<String, IBinder>();

      在ServiceManager中注册的Service都存储于sCache Map中,服务名作为key,value是Binder,通过Binder与Service通信。

      获取Service,通过方法:

      ContextImpl.java(frameworks/base/core/java/android/app/ContextImpl.java):

    @Override
        public Object getSystemService(String name) {
            if (vmIncorrectContextUseEnabled()) {
                // Check incorrect Context usage.
                if (isUiComponent(name) && !isSelfOrOuterUiContext()) {
                    final String errorMessage = "Tried to access visual service "
                            + SystemServiceRegistry.getSystemServiceClassName(name)
                            + " from a non-visual Context:" + getOuterContext();
                    final String message = "Visual services, such as WindowManager, WallpaperService "
                            + "or LayoutInflater should be accessed from Activity or other visual "
                            + "Context. Use an Activity or a Context created with "
                            + "Context#createWindowContext(int, Bundle), which are adjusted to "
                            + "the configuration and visual bounds of an area on screen.";
                    final Exception exception = new IllegalAccessException(errorMessage);
                    StrictMode.onIncorrectContextUsed(message, exception);
                    Log.e(TAG, errorMessage + " " + message, exception);
                }
            }
            return SystemServiceRegistry.getSystemService(this, name);
        }
    
        @Override
        public String getSystemServiceName(Class<?> serviceClass) {
            return SystemServiceRegistry.getSystemServiceName(serviceClass);
        }

      在启动SystemServer时,会将AMS、WMS、PMS等服务进行注册,注册的服务会存储在SystemServiceRegistry.SYSTEM_SERVICE_FETCHERS Map,存储的key是服务名。

      源码:frameworks/base/core/java/android/app/SystemServiceRegistry.java

    /**
        * Gets a system service from a given context.
        * @hide
        */
    public static Object getSystemService(ContextImpl ctx, String name) {
        if (name == null) {
            return null;
        }
        final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        if (fetcher == null) {
            if (sEnableServiceNotFoundWtf) {
                Slog.wtf(TAG, "Unknown manager requested: " + name);
            }
            return null;
        }
    
        final Object ret = fetcher.getService(ctx);
        if (sEnableServiceNotFoundWtf && ret == null) {
            // Some services do return null in certain situations, so don't do WTF for them.
            switch (name) {
                case Context.CONTENT_CAPTURE_MANAGER_SERVICE:
                case Context.APP_PREDICTION_SERVICE:
                case Context.INCREMENTAL_SERVICE:
                    return null;
            }
            Slog.wtf(TAG, "Manager wrapper not available: " + name);
            return null;
        }
        return ret;
    }

      最会调用到ServiceManager类中,getService函数:

    /**
         * Returns a reference to a service with the given name.
         *
         * @param name the name of the service to get
         * @return a reference to the service, or <code>null</code> if the service doesn't exist
         */
        @UnsupportedAppUsage
        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;
        }

    三、Service注册

      通过ServiceManager类中的addService函数注册:

    /**
         * 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
         */
        @UnsupportedAppUsage
        public static void addService(String name, IBinder service) {
            addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
        }

    四、系统服务什么时候注册 

      先看下SystemServer启动都做了哪些事

      图中启动各种服务,指的是启动系统服务,包括:AMS、PMS、WMS、PKMS等。

  • 相关阅读:
    程序员面试金典-面试题 16.15. 珠玑妙算
    程序员面试金典-面试题 16.14. 最佳直线
    程序员面试金典-面试题 16.13. 平分正方形
    程序员面试金典-面试题 16.11. 跳水板
    程序员面试金典-面试题 16.10. 生存人数
    程序员面试金典-面试题 16.08. 整数的英语表示
    程序员面试金典-面试题 16.07. 最大数值
    程序员面试金典-面试题 16.06. 最小差
    python学习笔记-47 UDP编程
    python学习笔记-46 TCP编程
  • 原文地址:https://www.cnblogs.com/naray/p/15226664.html
Copyright © 2020-2023  润新知