Android 8.0 SystemUI(二):プロセスの開始と初期化

12648 ワード

私は何が得意ですか.私がこの問題を考えたとき、頭の中は空白でした:あら、私は何でも知っていますが、得意だと言って、まだ手を出していません.これはどうしますか.そこでSystemUIシリーズの記事がありました.--猿湿Xoong
前編『図文並茂の紹介:D』で私はAndroid 8について.0の中のSystemUIは簡単に紹介して、自己感覚はとても良くて、また思考の導図はまた断面図で、知らない人に役に立つと思います.しかし、あまりにも簡単すぎて、水産物だと叱られたのかもしれません.qaq,ふふふふふふ!
この記事では、システムUIの起動とほぼ初期化について説明します.紙幅は前編より少し多いはずだ.ははは.
いつものように、まずカタログに載って、簡潔明瞭です.
概要
Bluetoothスイッチ、wifiスイッチ、時間、ユーザーナビゲーションバーなどのシステム状態をリアルタイムでフィードバックする必要があるため、SystemUIはシステムが起動するとすぐに持ち込まれます(SystemUI:私もしたくないです!疲れました!).通常の使用中のSystemUIでは、ほとんどの機能モジュールが動作状態であり、少数の機能、例えばスクリーンショット機能では、電源+音量の下ボタンを長く押すとカチカチスクリーンショットすることができます.
ここで、システム起動プロセスについて簡単に説明します.initプロセス->Zygoteプロセス->SystemServerプロセスです.
どうやってinitプロセスが始まったの?電源キーを押すと、システムに電源が入り、固定アドレスからROMに固化したBootloaderコードをRAMにロードして実行し、BootloaderブートがシステムOSを起動します.システムOSが引き上げられ、いくつかの列の初期化とシステム設定が完了すると、まずシステムファイルの中で「init」ファイルを探して、私たちのユーザー空間の最初のプロセスを開始します.
Emmm、遠くまで引っ張って、テーマに戻ります.最初のシステム起動プロセスに従って、私たちのSystemUIプロセスはSystemServerの起動中に持ち込まれます.
第1編の紹介から,SystemUIには多くのモジュールがあり,対応するインタフェースに対応していることが分かった.これらのモジュールには、次のような共通点があります.
  • は、各モジュールの初期化
  • を処理する.
  • 処理システムの状態変化
  • dump
  • を実行する
  • システムの起動が完了すると、対応する論理
  • を処理する.
    したがって,コードには,これらの共通点を抽出して抽象化し,SystemUI抽象クラスを形成する構造が以下のように現れる.
    このコードについて簡単に説明します.
  • は、サブクラスの初期化を完了するためのstartメソッドを定義し、このメソッドは抽象的なメソッドであるため、特定のサブクラスは必ず実装される.
  • onConfigurationChangedはシステムの状態変化を処理するコールバックであり、ここでの状態変化には、タイムゾーン変更、フォントサイズ変更、入力モード変更、画面サイズ変更、画面方向変更などが含まれる.
  • システムの多くのモジュールにはdumpメソッドが含まれています.dumpメソッドは、モジュールの内部状態を出力ストリームにdumpするために使用され、このメソッドは主にデバッグを支援するために使用される.開発者は開発中にadb shellによってdumpを実行することでシステムの内部状態を知ることができる.
  • onBootCompletedはシステム起動完了のコールバック方法です.

  • スクリーンショットサービスに加えて、言及モジュールは抽象クラスSystemUIを継承し、アプリケーションの起動時にそれぞれ初期化される.このような観点から、SystemUIアプリケーションは、これらの機能モジュールのコンテナに似ている.
    なお、Oreoでは、Nougatと比較して抽象クラスSystemUIの2つのサブクラス:BaseStatusBarとPhoneStatusBarが統合されてStatusBarに置き換えられている.java.SystemUIモジュールに触れたベテランドライバーはPhoneStatusBarというコアクラスに詳しいと信じていますが、今もほこり、土に帰っています.
    二、システムUI起動プロセス
    SystemServerはシステム内の様々な重要なサービスの起動を担当しているが、あいにく、SystemUIの重要性のため、彼女も起動されている列にあり、「Other」の地位にあるが~(SystemServerのコードはシステムサービスカテゴリに対して大きく3種類に分けられる:Bootstrap->Core->Other、SystemUIの起動はOtherの中にある).
    startOtherServices()では、AMSのシステムReady()メソッドを呼び出してAMS準備完了を通知します.SystemReady()はgoingCallbackというRunnableインスタンスをパラメータとして持ち,SoはAMSがsystemReady()の処理を完了するとこのRunnableのrun()メソッドをコールバックする.
    private void startOtherServices() {
        ... //    1000 
        mActivityManagerService.systemReady(() -> {
            Slog.i(TAG, "Making services ready");
            ...
            traceBeginAndSlog("StartSystemUI");
            try {
                startSystemUi(context, windowManagerF);
            } catch (Throwable e) {
                reportWtf("starting System UI", e);
            }
            ...
        }       
    }
    

    startSystemUIメソッドでは、赤枠のコンポーネント名でSystemUIのSystemUIサービスを開始します.
    Androidシステムでは、アプリケーションが起動すると、アプリケーションクラスが最初にインスタンス化されたクラスであることが保証され、アプリケーションのonCreateメソッドは、アプリケーション内のすべてのActivity、Service、BroadcastReceiverの作成よりも先に作成されます.
    SystemUIではSystemUIAPplicationが最初にインスタンス化されたクラスである.
    2つのサービスのセットが定義されています.
  • クラスは、すべてのユーザが共有するSystemUIサービスであり、例えば、Status Bar
  • のクラスは、各ユーザ固有のサービス
  • である.
    次の2つの配列は、この2つのサービスのセットを記録しています.
    前述のように、SystemUIは、機能モジュールの共通性を抽出する抽象クラスSystemUIを形成する.class、上図に示すすべてのタイプは、SystemUIのサブクラス実装です.
    次に、SystemUIAPplicationでは、BOOT_を受信するためにブロードキャスト受信機を主に登録するonCreateメソッドが呼び出される.COMPLETEDブロードキャストは、ブロードキャストを受信した後、各モジュールの関数onBootCompletedを呼び出す.
    SystemServerでSystemUIを起動するコードを覚えていますか?そのターゲットはSystemUIserviceのIntentです.
    システムアプリケーション家のonCreateが実行されると、このシステムUIserviceが起動します.このサービスonCreateメソッドは、起動時に呼び出されます.
    研究しないで知らないで、わあ、こいつはただの中継代理店(他の人にあなたを起動する機会を与える)だけで、信じないで見て、実際のコードは次の行だけで、下図を見てください.
    サービス全体で、本当に働いているのは赤い枠の中の一言だけです.よく見るとSystemUIAPplicationのstartServicesIfNeededメソッドが呼び出され、ぐるっと回って戻ってきました.
    これが各モジュールを起動する場所です.
    private void startServicesIfNeeded(Class>[] services) {
        if (mServicesStarted) {
            return;
        }
    
        if (!mBootCompleted) {
            // check to see if maybe it was already completed long before we began
            // see ActivityManagerService.finishBooting()
            if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
                // sys.boot_completed   ,   boot   ,AMS       
                mBootCompleted = true;
                if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
            }
        }
    
        Log.v(TAG, "Starting SystemUI services for user " + 
                Process.myUserHandle().getIdentifier() + ".");
        final int N = services.length;
        for (int i = 0; i < N; i++) {
            Class> cl = services[i];
            if (DEBUG) Log.d(TAG, "loading: " + cl);
            try {
                // SystemUIFactory  6.0    , 7.0    ,            SystemUI
                Object newService = SystemUIFactory.getInstance().createInstance(cl);
                mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InstantiationException ex) {
                throw new RuntimeException(ex);
            }
    
            //         Service      
            mServices[i].mContext = this;
            mServices[i].mComponents = mComponents;
            if (DEBUG) Log.d(TAG, "running: " + mServices[i]); 
            mServices[i].start();
    
            if (mBootCompleted) {
                mServices[i].onBootCompleted();
            }
        }
        ...
    }
    

    SystemUIAppの起動については、以下のように起動タイミングチャートをまとめました.
    さらに,各モジュール独自の初期化ロジックに到達する.
    ここではSystemBarsの初期について単独でさらに説明する.
    三、e.g.SystemBars
    SystemBarsには主にNavigationBarとStatusBarが含まれており、この2つのBarの対応位置を知らない学生は、次の『図文並茂の紹介:D』を見ることができます.
    Show the code:
    public class SystemBars extends SystemUI {
        private static final String TAG = "SystemBars";    
        private static final boolean DEBUG = false;    
        private static final int WAIT_FOR_BARS_TO_DIE = 500; 
           
        // in-process fallback implementation, per the product config
        private SystemUI mStatusBar;    
        
        @Override
        public void start() {    
            if (DEBUG) Log.d(TAG, "start");        
            createStatusBarFromConfig();
        }    
         
        @Override
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {        
            if (mStatusBar != null) {            
                mStatusBar.dump(fd, pw, args);
            }
        }    
        
        private void createStatusBarFromConfig() {        
            if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
            final String clsName = mContext.getString(R.string.config_statusBarComponent);        
            if (clsName == null || clsName.length() == 0) {
                throw andLog("No status bar component configured", null);
            }        
            Class> cls = null;        
            try {         
                cls = mContext.getClassLoader().loadClass(clsName);
            } catch (Throwable t) {    
                throw andLog("Error loading status bar component: " + clsName, t);
            }   
            try {       
                mStatusBar = (SystemUI) cls.newInstance();
            } catch (Throwable t) { 
                throw andLog("Error creating status bar component: " + clsName, t);
            }        
            mStatusBar.mContext = mContext; 
            mStatusBar.mComponents = mComponents; 
            mStatusBar.start(); 
            if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
        } 
     
        private RuntimeException andLog(String msg, Throwable t) {
            Log.w(TAG, msg, t)
            throw new RuntimeException(msg, t);
        }
    }
    

    このコードの説明は次のとおりです.
  • startメソッドシステムUIAPplication呼び出し
  • createStatusBarFromConfigメソッドを呼び出し、プロファイルの情報に基づいてStatus Barの初期化
  • を行う.
  • プロファイル内のインプリメンテーションクラスのクラス名を読み込みます.この値はframeworks/base/packages/systemUI/res/values/config.xmlで定義します.携帯電話では、その値は:com.android.systemui.statusbar.phone.StatusBar
  • クラスローダにより対応するクラス
  • をロードする.
  • 反射APIによるオブジェクトインスタンス
  • の作成
  • は、インスタンスのstartメソッドを最後に呼び出して初期化する.携帯機器ならここがStatusBar.startメソッド
  • なぜリソースファイルを読み込んでクラス名を取得し、反射してインスタンスを作成するのですか?
    メリット:
    ここでクラス名をリソースファイルに配置すると、TvやCarのような異なるプラットフォームでは、コードを変更することなく、プロファイルを変更するだけで、システム内のステータスバーの実装を置き換えることができ、モジュール間の結合を低減し、システムのメンテナンスコストを削減することができます.
    われわれの参考に値する.
    では、SystemUIの起動はここで終わります.具体的なSystemBarsやStatusBarは何をしているのか、後でフォローします.
    微信の公衆番号に注目してください:猿湿Xoong、最新の通知を取得します
    転載先:https://juejin.im/post/5ad586c951882548fe4a9de7