Androidシステムソース読解(18):Androidアプリケーションの表示


Androidシステムソース読解(18):Androidアプリケーションの表示
1.Activity Management Serviceの起動
前述の14章では、Systemプロセスが開始されると、システムの基本的なサービスがいくつか起動されます.起動時にActivityManagerServiceとPackageManagerServiceがあります.システムサーバでActivity Management Serviceを次のように起動します.
frameworks/base/services/java/com/android/server/SystemServer.java :
 // Activity manager runs the show.
 mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();

startServiceとは、Activity Management ServiceのインスタンスオブジェクトmActivity Management Serviceを作成し、Activity Management Serviceのlooperスレッドを起動することです.SystemServerが基本サービスを開始すると、mActivityManagerServiceのsystemReady関数が呼び出され、HomeActivityが起動します.
2.ホームActivityの起動
SystemServerのメインスレッドで現在呼び出されているsystemReady関数.この関数は、次にstartHomeActivity Locked関数を呼び出してHomeActivityを起動します.具体的には、次のようになります.
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java :
  boolean startHomeActivityLocked(int userId, String reason) {
        //...
        //       Home Intent,Intent category android.intent.category.home
        Intent intent = getHomeIntent();
        ActivityInfo aInfo =
            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(
                    aInfo.applicationInfo.packageName, aInfo.name));
            // Don't do this if the home app is currently being
            // instrumented.
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            //        home,          ,  app null
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
            if (app == null || app.instrumentationClass == null) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                //      HomeActivity
                mStackSupervisor.startHomeActivity(intent, aInfo, reason);
            }
        }
        return true;
    }

ここはmStackSupervisorに渡しました.startHomeActivity関数を使用してHomeActivityを起動すると、startActivity Locked関数が呼び出されます.ここでは,2章で一般アプリケーションのactivityを起動する手順を繰り返し,これ以上述べることはない.ここで、LauncherのManifestにはandroidのタイプが示されている.intent.category.ホーム、だから起動したのはLaucherアプリです.
3.Launcher展示応用
次に、LauncherのonCreate関数から始めます.コードの一部は次のとおりです.
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java :
LauncherAppState app = LauncherAppState.getInstance();
//  launcher   mModel callback  
mModel = app.setLauncher(this);

if (!mRestoring) {
    if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
        // If the user leaves launcher, then we should just load items asynchronously when
        // they return.
        mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);
     } else {
        // We only load the page synchronously if the user rotates (or triggers a
        // configuration change) while launcher is in the foreground
        //        
        mModel.startLoader(mWorkspace.getRestorePage());
      }
}

ここでmModelは、アプリケーション情報のロードを担当するLauncherModelオブジェクトです.リロードされたstartLoader関数:
 public void startLoader(int synchronousBindPage, int loadFlags) {
        //...
        synchronized (mLock) {
            //...
            // Don't bother to start the thread if we know it's not going to do anything
            if (mCallbacks != null && mCallbacks.get() != null) {
                //       ,             
                // If there is already one running, tell it to stop.
                stopLoaderLocked();
                //         
                mLoaderTask = new LoaderTask(mApp.getContext(), loadFlags);
                if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
                    //...
                } else {
                    //  workThread       
                    sWorkerThread.setPriority(Thread.NORM_PRIORITY);
                    //sWorker sWorkerThread Handler
                    sWorker.post(mLoaderTask);
                }
            }
        }
    }

すべてのインストールされたアプリケーション情報をロードするのは比較的時間がかかるプロセスであるため、非同期スレッドに渡して処理する必要があります.ここではまずロードタスクmLoaderTaskを作成し、sWorkerThreadに渡して処理します.sWorkerThreadはHandlerThreadであり、HandlerThreadは独立したスレッドであり、独自のlooperを持っていることを知っています.mLoaderTaskロードタスクは1回で完了しますが、なぜHandlerThreadで他のタスクを待つ必要があるのでしょうか.デスクトップアプリケーションは動的に追加および削除できるため、アプリケーションのロードは頻繁である可能性があります.ここでHandlerThreadを使用すると、ロードスレッドの重複作成を回避できます.
次はLoaderTaskを見てみましょう.run関数で具体的にどのようなタスクをしましたか.
packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java :
      public void run() {
            synchronized (mLock) {
                if (mStopped) {
                    return;
                }
                mIsLoaderTaskRunning = true;
            }
            // Optimize for end-user experience: if the Launcher is up and // running with the
            // All Apps interface in the foreground, load All Apps first. Otherwise, load the
            // workspace first (default).
            keep_running: {
                if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
                //  workspace
                loadAndBindWorkspace();
                if (mStopped) {
                    break keep_running;
                }
                waitForIdle();
                // second step
                if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
                //    
                loadAndBindAllApps();
            }
            //...
        }

WorkSpaceはAndroidデスクトップの分割画面で、各分割画面にはいくつかのアプリケーションがあります.ワークスペースをロードしてから、アプリケーションをロードするとユーザーの心理的な予想に合いますか?関数loadAndBindAllAppsは、アプリケーションがロードされたかどうかを判断し、情報がロードされている場合は、appをデスクトップに直接表示すればよい.ない場合は、次のような関数loadAllAppsを呼び出す必要があります.
packages/apps/Launcher3/src/com/android/luancher3/LauncherModel.java :
 private void loadAllApps() {
            final Callbacks oldCallbacks = mCallbacks.get();

            // Clear the list of apps
            mBgAllAppsList.clear();
            for (UserHandleCompat user : profiles) {
                // Query for the set of apps
                //     app  ,       PackageManagerService       
                final List apps = mLauncherApps.getActivityList(null, user);

                // Create the ApplicationInfos
                for (int i = 0; i < apps.size(); i++) {
                    LauncherActivityInfoCompat app = apps.get(i);
                    //          AppInfo
                    // This builds the icon bitmaps.
                    mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache));
                }
            }
            //...
            // Huh? Shouldn't this be inside the Runnable below?
            final ArrayList added = mBgAllAppsList.added;
            mBgAllAppsList.added = new ArrayList();

            //       Launcher      HandlerThread    
            //        ,         ui  ,mHandler     Handler
            // Post callback on main thread
            mHandler.post(new Runnable() {
                public void run() {
                    //  callback  launcher
                    final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                    if (callbacks != null) {
                       //      
                        callbacks.bindAllApplications(added);
                       //...
                    } else {
                        //...
                    }
                }
            });
            //...
        }

mLauncherApps.getActivity Listがapp情報を取得する方法は、PackageManagerに要求を送信することによって実現される.次にLauncherメインスレッドに戻り、アプリケーションアイコンの表示を開始します.まず、このコールバック関数を見てみましょう.
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java :
   /**
     * Add the icons for all apps.
     *
     * Implementation of the method from LauncherModel.Callbacks.
     */
    public void bindAllApplications(final ArrayList apps) {
        //...
        if (mAppsView != null) {
            //mAppsView        view
            mAppsView.setApps(apps);
        }
        //...
    }

mAppsViewはviewのコンテナであり、AlphabeticalAppsListリストを維持し、アプリケーションの情報を保存します.新しいアプリケーション情報を追加すると、ホーム上のアプリケーションが更新されます.ホーム上のアイコンがクリックされると、アプリケーションの起動がトリガーされます.