Android--ネットワーク関連のシステムサービス起動の簡単な分析


Android--ネットワーク関連のシステムサービス起動の簡単な分析
Androidの多くのシステムサービスはSystemServerで開始されています.一般的には2つの方法があります.
  • SystemServiceManager.startServcie()
  • ServiceManageraddService()

  • 前者も後者によってAndroidのサービスシステムに1つのサービスを追加した.AndroidのサービスシステムはBinderに基づいて実現されていることを知っています.Javaコードで呼び出されるこれらの起動・追加サービスの方法は,実際には下位層のC++が実現するサービス体系のコードパッケージであり,ここでは深く検討しない.
    Ethernetサービスを例に、サービスの開始手順を簡単に説明します.SystemServerにアクセスするには:
    private static final String ETHERNET_SERVICE_CLASS =
                "com.android.server.ethernet.EthernetService";
    
    if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
                        mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
                        mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
    }
    Ethernetがサポートされている場合はSystemServiceManagementが呼び出されます.startService()メソッドは、サービスを開始します.
     /**
         * Starts a service by class name.
         *
         * @return The service instance.
         */
        @SuppressWarnings("unchecked")
        public SystemService startService(String className) {
            final Class serviceClass;
            try {
                serviceClass = (Class)Class.forName(className);
            } catch (ClassNotFoundException ex) {
                Slog.i(TAG, "Starting " + className);
                throw new RuntimeException("Failed to create service " + className
                        + ": service class not found, usually indicates that the caller should "
                        + "have called PackageManager.hasSystemFeature() to check whether the "
                        + "feature is available on this device before trying to start the "
                        + "services that implement it", ex);
            }
            return startService(serviceClass);
        }
    
        /**
         * Creates and starts a system service. The class must be a subclass of
         * {@link com.android.server.SystemService}.
         *
         * @param serviceClass A Java class that implements the SystemService interface.
         * @return The service instance, never null.
         * @throws RuntimeException if the service fails to start.
         */
        @SuppressWarnings("unchecked")
        public  T startService(Class serviceClass) {
            final String name = serviceClass.getName();
            Slog.i(TAG, "Starting " + name);
    
            // Create the service.
            if (!SystemService.class.isAssignableFrom(serviceClass)) {
                throw new RuntimeException("Failed to create " + name
                        + ": service must extend " + SystemService.class.getName());
            }
            final T service;
            try {
                Constructor constructor = serviceClass.getConstructor(Context.class);
                service = constructor.newInstance(mContext);
            } catch (InstantiationException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service could not be instantiated", ex);
            } catch (IllegalAccessException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service must have a public constructor with a Context argument", ex);
            } catch (NoSuchMethodException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service must have a public constructor with a Context argument", ex);
            } catch (InvocationTargetException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service constructor threw an exception", ex);
            }
    
            // Register it.
            mServices.add(service);
    
            // Start it.
            try {
                service.onStart();
            } catch (RuntimeException ex) {
                throw new RuntimeException("Failed to start service " + name
                        + ": onStart threw an exception", ex);
            }
            return service;
        }
    startService()反射により構造関数を呼び出してEthernetサービスのインスタンス化対象を得る.また,EthernetサービスではEthernet Managerのサービス側であるEthernetサービスインプラントオブジェクトが作成されます.EthernetサービスのonStart()メソッドを呼び出し、このサービスを登録します.
    public final class EthernetService extends SystemService {
    
        private static final String TAG = "EthernetService";
        final EthernetServiceImpl mImpl;
    
        public EthernetService(Context context) {
            super(context);
            mImpl = new EthernetServiceImpl(context);
        }
    
        @Override
        public void onStart() {
            Log.i(TAG, "Registering service " + Context.ETHERNET_SERVICE);
            publishBinderService(Context.ETHERNET_SERVICE, mImpl);
        }
    
        @Override
        public void onBootPhase(int phase) {
            if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
                mImpl.start();
            }
        }
    }
    
    Ethernetサービスはシステムサービスから継承されます.SystemServiceは抽象クラスであり、システムプロセスで実行されるサービスを表すために設計されています.ライフサイクルフェーズによっては、ライフサイクルの異なるフェーズでいくつかの作業を完了するために、多くのシステムコールバック方法が提供されます.ここでは主に2つの方法を見ます.
        /**
         * Called when the dependencies listed in the @Service class-annotation are available
         * and after the chosen start phase.
         * When this method returns, the service should be published.
         */
        public abstract void onStart();
    
        /**
         * Called on each phase of the boot process. Phases before the service's start phase
         * (as defined in the @Service annotation) are never received.
         *
         * @param phase The current boot phase.
         */
        public void onBootPhase(int phase) {}
    サービスを開始する必要がある場合、onStart()メソッドを呼び出してサービスをServiceManagerに登録します.
     /**
         * Publish the service so it is accessible to other services and apps.
         */
        protected final void publishBinderService(String name, IBinder service) {
            publishBinderService(name, service, false);
        }
    
        /**
         * Publish the service so it is accessible to other services and apps.
         */
        protected final void publishBinderService(String name, IBinder service,
                boolean allowIsolated) {
            ServiceManager.addService(name, service, allowIsolated);
        }

    onBootPhase()はbootの各フェーズで呼び出されます.EthernetサービスでシステムがPHASE_にある場合SYSTEM_SERVICES_READYフェーズの場合、Ethernet ServiceImplが呼び出されます.start()メソッドでは、Ethernetの初期化作業を行います.
     public void start() {
            Log.i(TAG, "Starting Ethernet service");
    
            HandlerThread handlerThread = new HandlerThread("EthernetServiceThread");
            handlerThread.start();
            mHandler = new Handler(handlerThread.getLooper());
    
            mTracker.start(mContext, mHandler);//EthernetNetworkFactory
    
            mStarted.set(true);
        }
    Ethernet Managerがインタフェースを外部に露出し,Ethernet ServiceImplがEthernet Managerにサービスを提供し,Ethernet NetworkFactoryがすべてのネットワーク管理操作を請け負う.
    これでEthernetサービスの起動プロセスは終了します.