2012年07月09日

Android パッケージインストール処理のしくみを追う

はてなブックマークに登録

身近な話題でありながら中身のよくわからないことを調べてみるのは興味ぶかいもので、そこから得た知識が意外なところで役に立つことも少なくありません。かねてより Android 環境へアプリケーションをインストールする際に内部でどのような処理が行われるのかに関心を持っていたのですが、知りたい情報がなかなか見当たらないため手元で調査を行いました。その内容を公開します。

まとめ

※クリックすると大きな図が開きます

※PackageInstaller を起動した状態での関連プロセスの例

$ ps
USER     PID   PPID  VSIZE  RSS     WCHAN    PC         NAME
root      1     0     268    180   c009b74c 0000875c S /init
root      36    1     812    244   c02181f4 afd0b45c S /system/bin/installd
root      33    1     60900  16628 c009b74c afd0b844 S zygote
system    62    33    126452 28368 ffffffff afd0b6fc S system_server
app_30    372   33    74876  18852 ffffffff afd0c51c S com.android.packageinstaller
                              :
※Package Manager Service と installd プロセスの連携用 UNIX ドメインソケット
$ ls -l /dev/socket/installd
srw------- system   system            2012-07-04 11:43 installd
  • Android OS 上でパッケージインストールにもっとも深い関わりを持つシステムサービスは、system_server プロセス内で稼動する Package Manager Service と、単独のネイティブプロセスとして動作する installd デーモンである。両者はいずれもシステムブート時に動作を開始する。
  • Package Manager Service は起動時に /data/system/packages.xml ファイルより現システム上のパッケージに関する情報を読み込んで実状と照合し、何らかの不整合があれば再インストール処理を含む自動復旧を試みた上で同ファイルへ最新の状態を反映する。
  • Package Manager Service は起動時に /system/etc/permissions/platform.xml を参照し既定の Android パーミッションに関する情報をロードし、同ディレクトリ下の他の *.xml より当該端末がカバーする機能の情報をロードする。
  • installd デーモンは UNIX ドメインソケット /dev/socket/installd 経由で Package Manager Service から処理要求を受信し、パッケージのインストール・アンインストールまわりの一連の手順のうち root 権限を要する処理を主に担当する。

  • PackageInstaller は通常のパッケージを対話的にインストールするための Android 既定のアプリケーションである。ユーザからインストール指示を受けると PackageInstaller は InstallAppProgress アクティビティを呼び出し、InstallAppProgress は Package Manager Service の installPackage() API 経由で当該パッケージのインストールをシステムへ依頼する。
  • Package Manager Service はパッケージインストール要求を受けると当該パッケージの情報を取得し以下を実施する
    - インストール処理用のキューへパッケージ情報を追加〜順番待ち
    - 当該パッケージの適切なインストールロケーションを判定
    - 新規インストール/更新インストールの判別
    - 所定のディレクトリへの apk ファイルのコピー
    - 当該アプリの UID の決定
    - installd デーモンへ処理を要求
         - アプリケーションディレクトリの作成とパーミッション設定
         - dex コードのキャッシュディレクトリへの切り出し
    - 最新の状態を /data/system/packages.xml および packages.list へ反映
    - インストール完了の旨をパッケージ名を添えてシステムへブロードキャスト
     (新規の場合:Intent.ACTION_PACKAGE_ADDED
       更新の場合:Intent.ACTION_PACKAGE_REPLACED)

  • 上記の PackageInstaller 経由でのインストール経路とは別に、Package Manager Service は内部クラス「AppDirObserver」による非対話式のインストール経路を用意している。 AppDirObserver は android.os.FileObserver の派生クラスであり、所定のディレクトリ直下に .apk の拡張子を持つファイルが配置/削除されると自動的にシステムへのインストール/アンインストールを行う機能を持つ。(※別経路でインストールが行われた場合に重複処理発生を抑制するための機構を備える) Package Manager Service は起動時に /system/app, /data/app, /data/app-private, /system/framwrorks, /vendor/app の各ディレクトリを対象に AppDirObserver クラスのインスタンスを生成する。なお、これらのディレクトリへの書き込みには特権が必要であるため一般のアプリケーションプロセスから直接 AppDirObserver の提供する機構を利用することはできない。

コード読み

パッケージインストール処理を構成する一連のソースコードはかなりのボリュームがありますが、コードリーディングの一助として注釈を添えた抜粋を以下に掲載します。コードはいずれも 2012-07-06 現在の内容です。 なお、オンラインソースへのリンクには便宜上 http://android.git.linaro.org/ を使用しています。

クラス・メソッドの参照関係(一部)
※リンク末尾の「(*)」はオンラインソースへのリンクであることをを示す
※リンク末尾の「-」は引数の異なるオーバーロードメソッドであることをを示す

 ■ system_server プロセスおよび installd プロセスの起動(システムブート時)
    - /init.rcPackageManagerService のスタートアップ
    - PackageManagerService.PackageManagerService()
        - Settings
            - PackageSetting (*)
        - Installer
        - PackageManagerService.readPermissions()
            - PackageManagerService.readPermissionsFromXml()
        - Settings.readLPw()
        - PackageManagerService.AppDirObserver
        - PackageManagerService.scanDirLI()
            - PackageParser.Package
            - PackageManagerService.scanPackageLI()
                - PackageParser.Package
                - PackageParser.parsePackage()
                    - PackageParser.parsePackage() -
                - PackageManagerService.collectCertificatesLI()
                    - PackageParser.collectCertificates()
                        - PackageParser.loadCertificates()
                - PackageManagerService.scanPackageLI() -
                    - Settings.getPackageLPw()
                        - Settings.getPackageLPw() -
                    - Installer.remove()
                        - installd.c
                            - commands.c
                            - utils.c (*)
                    - Installer.install()
                        - installd.c
                            - commands.c
                            - utils.c (*)
        - Settings.writeLPr()
            - Settings.writePermissionLPr()
            - Settings.writePackageLPr()
                - PackageSignatures.writeXml()
            - Settings.writeDisabledSysPackageLPr()
            - PreferredActivity.writeToXml()
                - PreferredComponent.writeToXml()
                - IntentFilter.writeToXml()installd デーモンのスタートアップ
    - installd.c
        - commands.c
        - utils.c (*)PackageInstaller から InstallAppProgress へインストール要求の引き渡し
    - PackageInstallerActivity.onCreate()
        - PackageUtil.getPackageInfo()
            - PackageParser.parsePackage()
                - PackageParser.Package
                - PackageParser.parsePackage() -
        - ApplicationInfo  (*)
    - PackageInstallerActivity.onClick()InstallAppProgress からシステムへインストール要求〜インストール実処理
    - InstallAppProgress.onCreate()
    - InstallAppProgress.initView()
      - InstallAppProgress.PackageInstallObserver
      - PackageManager.installPackage()
        - PackageManagerService.installPackage()
          - PackageManagerService.installPackageWithVerification
            - PackageManagerService.PackageHandler [INIT_COPY]
              - PackageManagerService.HandlerParams
              - PackageManagerService.connectToService()
            - PackageManagerService.PackageHandler [MCS_BOUND]
              - PackageManagerService.HandlerParams.startCopy()
                - PackageManagerService.PackageHandler [MCS_GIVE_UP]
                - PackageManagerService.PackageHandler [MCS_RECONNECT]
                  - PackageManagerService.disconnectService()
                  - PackageManagerService.connectToService()
                - PackageManagerService.InstallParams.handleStartCopy()
                  - PackageManagerService.InstallParams.installLocationPolicy()
                  - PackageManagerService.InstallParams.createInstallArgs()
                    - PackageManagerService.FileInstallArgs.FileInstallArgs()
                  - PackageManagerService.FileInstallArgs.copyApk()
                    - PackageManagerService.FileInstallArgs.createCopyFile()
                    - PackageManagerService.FileInstallArgs.setPermissions()
                    - IMediaContainerService.copyResource()
                      - DefaultContainerService.IMediaContainerService.Stub.copyResource()
                        - DefaultContainerService.copyFile()
                          - DefaultContainerService.copyToFile()
                            - DefaultContainerService.copyToFile() -
                          - DefaultContainerService.copyToFile() -
                - PackageManagerService.InstallParams.handleReturnCode()
                  - PackageManagerService.processPendingInstall()
                    - PackageManagerService.FileInstallArgs.doPreInstall()
                      - PackageManagerService.FileInstallArgs.cleanUp()
                    - PackageManagerService.installPackageLI()
                      - PackageParser.parsePackage()
                        - PackageParser.Package
                        - PackageParser.parsePackage() -
                      - PackageManagerService.FileInstallArgs.doRename()
                        - PackageManagerService.FileInstallArgs.cleanUp()
                        - PackageManagerService.FileInstallArgs.getResourcePathFromCodePath()
                        - PackageManagerService.FileInstallArgs.setPermissions()
                      - PackageManagerService.installNewPackageLI()
                        - PackageManagerService.scanPackageLI()
                          - PackageSetting (*)
                          - Settings.getPackageLPw()
                            - Settings.getPackageLPw() -
                          - Installer.remove()
                            - installd.c
                              - commands.c
                              - utils.c (*)
                          - Installer.install()
                            - installd.c
                              - commands.c
                              - utils.c (*)
                        - PackageManagerService.updateSettingsLI()
                          - Settings.writeLPr()
                            - Settings.writePermissionLPr()
                            - Settings.writePackageLPr()
                              - PackageSignatures.writeXml()
                            - Settings.writeDisabledSysPackageLPr()
                            - PreferredActivity.writeToXml()
                              - PreferredComponent.writeToXml()
                              - IntentFilter.writeToXml()
                          - PackageManagerService.moveDexFilesLI()
                            - Installer.movedex()
                              - installd.c
                                - commands.c
                                - utils.c (*)
                          - PackageManagerService.setPermissionsLI()
                          - Settings.writeLPr()
                                   : (前出)
                    - PackageManagerService.FileInstallArgs.doPostInstall()
                      - PackageManagerService.FileInstallArgs.cleanUp()
                    - PackageManagerService.PackageHandler [POST_INSTALL]
                      - PackageManagerService.sendPackageBroadcast()
                      - InstallAppProgress.PackageInstallObserver.packageInstalled()
                        - InstallAppProgress.handleMessage [INSTALL_COMPLETE]
              - PackageManagerService.PackageHandler [MCS_UNBIND]
                - PackageManagerService.disconnectService()AppDirObserver によるインストール・アンインストールの自動処理
    - PackageManagerService.AppDirObserver.onEvent()
        - PackageManagerService.scanPackageLI()
            - PackageParser.Package
            - PackageParser.parsePackage()
                - PackageParser.parsePackage() -
            - PackageSetting (*)
            - PackageManagerService.collectCertificatesLI()
                - PackageParser.collectCertificates()
                    - PackageParser.loadCertificates()
            - PackageManagerService.scanPackageLI() -
                - Settings.getPackageLPw()
                    - Settings.getPackageLPw() -
                - Installer.remove()
                    - installd.c
                        - commands.c
                        - utils.c (*)
                - Installer.install()
                    - installd.c
                        - commands.c
                        - utils.c (*)
        - Settings.writeLPr()
            - Settings.writePermissionLPr()
            - Settings.writePackageLPr()
                - PackageSignatures.writeXml()
            - Settings.writeDisabledSysPackageLPr()
            - PreferredActivity.writeToXml()
                - PreferredComponent.writeToXml()
                - IntentFilter.writeToXml()
        - PackageManagerService.sendPackageBroadcast()

system_server プロセスおよび installd プロセスの起動
(システムブート時)

実行環境の /init.rc より


                 :
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd
                 :

service installd /system/bin/installd
    socket installd stream 600 system system
                 :

PackageManagerService のスタートアップ

frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より


PackageManagerService スタートアップ

  17 package com.android.server.pm;
                       :

 152 public class PackageManagerService extends IPackageManager.Stub {
                       :

         // 定義・変数
 166     static final boolean MULTIPLE_APPLICATION_UIDS = true;
 167     private static final int RADIO_UID = Process.PHONE_UID;
 168     private static final int LOG_UID = Process.LOG_UID;
 169     private static final int NFC_UID = Process.NFC_UID;
 170     static final int FIRST_APPLICATION_UID =
 171         Process.FIRST_APPLICATION_UID;
 172     static final int MAX_APPLICATION_UIDS = 1000;
 173 
 174     private static final boolean GET_CERTIFICATES = true;
 175 
 176     private static final int REMOVE_EVENTS =
 177         FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
 178     private static final int ADD_EVENTS =
 179         FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
 180 
 181     private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
 182     // Suffix used during package installation when copying/moving
 183     // package apks to install directory.
 184     private static final String INSTALL_PACKAGE_SUFFIX = "-";
                       :

 209     static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
 210 
 211     static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
 212             DEFAULT_CONTAINER_PACKAGE,
 213             "com.android.defcontainer.DefaultContainerService");
 214 
 215     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
 216 
 217     private static final String LIB_DIR_NAME = "lib";
 218 
 219     static final String mTempContainerPrefix = "smdl2tmp";
 220 
 221     final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
 222             Process.THREAD_PRIORITY_BACKGROUND);
 223     final PackageHandler mHandler;
 224 
 225     final int mSdkVersion = Build.VERSION.SDK_INT;
 226     final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
 227             ? null : Build.VERSION.CODENAME;
 228 
 229     final Context mContext;
 230     final boolean mFactoryTest;
 231     final boolean mOnlyCore;
 232     final boolean mNoDexOpt;
 233     final DisplayMetrics mMetrics;
 234     final int mDefParseFlags;
 235     final String[] mSeparateProcesses;
 236 
 237     // This is where all application persistent data goes.
 238     final File mAppDataDir;
 239 
 240     // This is where all application persistent data goes for secondary users.
 241     final File mUserAppDataDir;
 242 
 243     // This is the object monitoring the framework dir.
 244     final FileObserver mFrameworkInstallObserver;
 245 
 246     // This is the object monitoring the system app dir.
 247     final FileObserver mSystemInstallObserver;
 248 
 249     // This is the object monitoring the system app dir.
 250     final FileObserver mVendorInstallObserver;
 251 
 252     // This is the object monitoring mAppInstallDir.
 253     final FileObserver mAppInstallObserver;
 254 
 255     // This is the object monitoring mDrmAppPrivateInstallDir.
 256     final FileObserver mDrmAppInstallObserver;
 257 
 258     // Used for priviledge escalation.  MUST NOT BE CALLED WITH mPackages
 259     // LOCK HELD.  Can be called with mInstallLock held.
 260     final Installer mInstaller;
 261 
 262     final File mFrameworkDir;
 263     final File mSystemAppDir;
 264     final File mVendorAppDir;
 265     final File mAppInstallDir;
 266     final File mDalvikCacheDir;
 267 
 268     // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
 269     // apps.
 270     final File mDrmAppPrivateInstallDir;
 271 
 272     // ----------------------------------------------------------------
 273 
 274     // Lock for state used when installing and doing other long running
 275     // operations.  Methods that must be called with this lock held have
 276     // the prefix "LI".
 277     final Object mInstallLock = new Object();
 278 
 279     // These are the directories in the 3rd party applications installed dir
 280     // that we have currently loaded packages from.  Keys are the application's
 281     // installed zip file (absolute codePath), and values are Package.
 282     final HashMap<String, PackageParser.Package> mAppDirs =
 283             new HashMap<String, PackageParser.Package>();
 284 
 285     // Information for the parser to write more useful error messages.
 286     File mScanningPath;
 287     int mLastScanError;
 288 
 289     final int[] mOutPermissions = new int[3];
 290 
 291     // ----------------------------------------------------------------
 292 
 293     // Keys are String (package name), values are Package.  This also serves
 294     // as the lock for the global state.  Methods that must be called with
 295     // this lock held have the prefix "LP".
 296     final HashMap<String, PackageParser.Package> mPackages =
 297             new HashMap<String, PackageParser.Package>();
 298 
 299     final Settings mSettings;
 300     boolean mRestoredSettings;
 301 
 302     // Group-ids that are given to all packages as read from etc/permissions/*.xml.
 303     int[] mGlobalGids;
 304 
 305     // These are the built-in uid -> permission mappings that were read from the
 306     // etc/permissions.xml file.
 307     final SparseArray<HashSet<String>> mSystemPermissions =
 308             new SparseArray<HashSet<String>>();
 309 
 310     // These are the built-in shared libraries that were read from the
 311     // etc/permissions.xml file.
 312     final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
 313 
 314     // Temporary for building the final shared libraries for an .apk.
 315     String[] mTmpSharedLibraries = null;
 316 
 317     // These are the features this devices supports that were read from the
 318     // etc/permissions.xml file.
 319     final HashMap<String, FeatureInfo> mAvailableFeatures =
 320             new HashMap<String, FeatureInfo>();
 321 
 322     // All available activities, for your resolving pleasure.
 323     final ActivityIntentResolver mActivities =
 324             new ActivityIntentResolver();
 325 
 326     // All available receivers, for your resolving pleasure.
 327     final ActivityIntentResolver mReceivers =
 328             new ActivityIntentResolver();
 329 
 330     // All available services, for your resolving pleasure.
 331     final ServiceIntentResolver mServices = new ServiceIntentResolver();
 332 
 333     // Keys are String (provider class name), values are Provider.
 334     final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
 335             new HashMap<ComponentName, PackageParser.Provider>();
 336 
 337     // Mapping from provider base names (first directory in content URI codePath)
 338     // to the provider information.
 339     final HashMap<String, PackageParser.Provider> mProviders =
 340             new HashMap<String, PackageParser.Provider>();
 341 
 342     // Mapping from instrumentation class names to info about them.
 343     final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
 344             new HashMap<ComponentName, PackageParser.Instrumentation>();
 345 
 346     // Mapping from permission names to info about them.
 347     final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
 348             new HashMap<String, PackageParser.PermissionGroup>();
 349 
 350     // Packages whose data we have transfered into another package, thus
 351     // should no longer exist.
 352     final HashSet<String> mTransferedPackages = new HashSet<String>();
 353     
 354     // Broadcast actions that are only available to the system.
 355     final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
 356 
 357     /** List of packages waiting for verification. */
 358     final SparseArray<PackageVerificationState> mPendingVerification
 359             = new SparseArray<PackageVerificationState>();
 360 
 361     final ArrayList<PackageParser.Package> mDeferredDexOpt =
 362             new ArrayList<PackageParser.Package>();
 363 
 364     /** Token for keys in mPendingVerification. */
 365     private int mPendingVerificationToken = 0;
 366 
 367     boolean mSystemReady;
 368     boolean mSafeMode;
 369     boolean mHasSystemUidErrors;
 370 
 371     ApplicationInfo mAndroidApplication;
 372     final ActivityInfo mResolveActivity = new ActivityInfo();
 373     final ResolveInfo mResolveInfo = new ResolveInfo();
 374     ComponentName mResolveComponentName;
 375     PackageParser.Package mPlatformPackage;
 376 
 377     // Set of pending broadcasts for aggregating enable/disable of components.
 378     final HashMap<String, ArrayList<String>> mPendingBroadcasts
 379             = new HashMap<String, ArrayList<String>>();
 380     // Service Connection to remote media container service to copy
 381     // package uri's from external media onto secure containers
 382     // or internal storage.
 383     private IMediaContainerService mContainerService = null;
                       :

 406     final UserManager mUserManager;
 407 
         // DefaultContainerService との接続・切断時のハンドラ
 408     final private DefaultContainerConnection mDefContainerConn =
 409             new DefaultContainerConnection();
 410     class DefaultContainerConnection implements ServiceConnection {
 411         public void onServiceConnected(ComponentName name, IBinder service) {
 412             if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
 413             IMediaContainerService imcs =
 414                 IMediaContainerService.Stub.asInterface(service);
                 // 接続確立時に自動的にハンドラへ MCS_BOUND メッセージを送出する
 415             mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
 416         }
 417 
 418         public void onServiceDisconnected(ComponentName name) {
 419             if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
 420         }
 421     };
 422 
 423     // Recordkeeping of restore-after-install operations that are currently in flight
 424     // between the Package Manager and the Backup Manager
 425     class PostInstallData {
 426         public InstallArgs args;
 427         public PackageInstalledInfo res;
 428 
 429         PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
 430             args = _a;
 431             res = _r;
 432         }
 433     };
 434     final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
 435     int mNextInstallToken = 1;  // nonzero; will be wrapped back to 1 when ++ overflows
 436 
 437     private final String mRequiredVerifierPackage;
                      :

         // コンストラクタここから
 860     public PackageManagerService(Context context, boolean factoryTest, boolean onlyCore) {
 861         EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
 862                 SystemClock.uptimeMillis());
 863 
 864         if (mSdkVersion <= 0) {
 865             Slog.w(TAG, "**** ro.build.version.sdk not set!");
 866         }
 867 
 868         mContext = context;
 869         mFactoryTest = factoryTest;
 870         mOnlyCore = onlyCore;
 871         mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
 872         mMetrics = new DisplayMetrics();

             // パッケージまわりの情報を一括管理するクラス
 873         mSettings = new Settings();

             // 決め打ちの4 つの SharedUserId を設定
 874         mSettings.addSharedUserLPw("android.uid.system",
 875                 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
 876         mSettings.addSharedUserLPw("android.uid.phone",
 877                 MULTIPLE_APPLICATION_UIDS
 878                         ? RADIO_UID : FIRST_APPLICATION_UID,
 879                 ApplicationInfo.FLAG_SYSTEM);
 880         mSettings.addSharedUserLPw("android.uid.log",
 881                 MULTIPLE_APPLICATION_UIDS
 882                         ? LOG_UID : FIRST_APPLICATION_UID,
 883                 ApplicationInfo.FLAG_SYSTEM);
 884         mSettings.addSharedUserLPw("android.uid.nfc",
 885                 MULTIPLE_APPLICATION_UIDS
 886                         ? NFC_UID : FIRST_APPLICATION_UID,
 887                 ApplicationInfo.FLAG_SYSTEM);
                       :

             // Installer クラスは installd ソケットへの書き込みを行う
 906         mInstaller = new Installer();
 907 
 908         WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
 909         Display d = wm.getDefaultDisplay();
 910         d.getMetrics(mMetrics);
 911 
 912         synchronized (mInstallLock) {
 913         // writer
 914         synchronized (mPackages) {
                 // メッセージハンドラを起動
 915             mHandlerThread.start();
 916             mHandler = new PackageHandler(mHandlerThread.getLooper());
 917 
                 // "/data/data", "/data/user", "/data/app-private"
 918             File dataDir = Environment.getDataDirectory();
 919             mAppDataDir = new File(dataDir, "data");
 920             mUserAppDataDir = new File(dataDir, "user");
 921             mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
 922 
 923             mUserManager = new UserManager(mInstaller, mUserAppDataDir);
 924 
                 // /system/etc/permissions/platform.xml および *.xml の読み込み
 925             readPermissions();
 926 
                 // /data/system/packages.xml の読み込み
 927             mRestoredSettings = mSettings.readLPw();
 928             long startTime = SystemClock.uptimeMillis();
 929 
 930             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
 931                     startTime);
 932 
 933             // Set flag to monitor and not change apk file paths when
 934             // scanning install directories.
 935             int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX;
 936             if (mNoDexOpt) {
 937                 Slog.w(TAG, "Running ENG build: no pre-dexopt!");
 938                 scanMode |= SCAN_NO_DEX;
 939             }
 940 
 941             final HashSet<String> libFiles = new HashSet<String>();
 942 
                 // "/framework", "/data/dalvik-cache"
 943             mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
 944             mDalvikCacheDir = new File(dataDir, "dalvik-cache");
                              :

                 // /system/app 下を AppDirObserver で監視
1057             // Collect all system packages.
1058             mSystemAppDir = new File(Environment.getRootDirectory(), "app");
1059             mSystemInstallObserver = new AppDirObserver(
1060                 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
1061             mSystemInstallObserver.startWatching();
1062             scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
1063                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
1064             

                 // /vendor/app 下を AppDirObserver で監視
1065             // Collect all vendor packages.
1066             mVendorAppDir = new File("/vendor/app");
1067             mVendorInstallObserver = new AppDirObserver(
1068                 mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
1069             mVendorInstallObserver.startWatching();
1070             scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
1071                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
1072 
1073             if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
1074             mInstaller.moveFiles();
1075 

                 // すでに存在しないシステムパッケージを削除
1076             // Prune any system packages that no longer exist.
1077             if (!mOnlyCore) {
1078                 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
1079                 while (psit.hasNext()) {
1080                     PackageSetting ps = psit.next();
1081                     if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
1082                             && !mPackages.containsKey(ps.name)
1083                             && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
1084                         psit.remove();
1085                         String msg = "System package " + ps.name
1086                                 + " no longer exists; wiping its data";
1087                         reportSettingsProblem(Log.WARN, msg);
1088                         mInstaller.remove(ps.name, 0);
1089                         mUserManager.removePackageForAllUsers(ps.name);
1090                     }
1091                 }
1092             }
1093             

                 // "/data/app"
1094             mAppInstallDir = new File(dataDir, "app");

                 // インストール未了のパッケージファイルを探索して削除
1095             //look for any incomplete package installations
1096             ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
1097             //clean up list
1098             for(int i = 0; i < deletePkgsList.size(); i++) {
1099                 //clean up here
1100                 cleanupInstallFailedPackage(deletePkgsList.get(i));
1101             }
1102             //delete tmp files
1103             deleteTempPackageFiles();
1104 
1105             if (!mOnlyCore) {
1106                 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
1107                         SystemClock.uptimeMillis());

                     // /data/app 下を AppDirObserver で監視
1108                 mAppInstallObserver = new AppDirObserver(
1109                     mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
1110                 mAppInstallObserver.startWatching();
1111                 scanDirLI(mAppInstallDir, 0, scanMode, 0);
1112     

                     // /data/app-private 下を AppDirObserver で監視
1113                 mDrmAppInstallObserver = new AppDirObserver(
1114                     mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
1115                 mDrmAppInstallObserver.startWatching();
1116                 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
1117                         scanMode, 0);
1118             } else {
1119                 mAppInstallObserver = null;
1120                 mDrmAppInstallObserver = null;
1121             }
                          :

1140             mSettings.mInternalSdkPlatform = mSdkVersion;
1141             
1142             updatePermissionsLPw(null, null, true, regrantPermissions, regrantPermissions);
1143 

                 // /data/system/packages.xml, packages.list を最新の状態に更新
1144             // can downgrade to reader
1145             mSettings.writeLPr();
                   :

1156         } // synchronized (mPackages)
1157         } // synchronized (mInstallLock)
1158     }

installd デーモンのスタートアップ

platform/frameworks/base/cmds/installd/installd.c より

installd デーモン

  17 #include "installd.h"
                  :

     // 各コマンドに対応する関数のエントリポイント
  29 static int do_install(char **arg, char reply[REPLY_MAX])
  30 {
  31     return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
  32 }
  33 
  34 static int do_dexopt(char **arg, char reply[REPLY_MAX])
  35 {
  36         /* apk_path, uid, is_public */
  37     return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]));
  38 }
  39 
  40 static int do_move_dex(char **arg, char reply[REPLY_MAX])
  41 {
  42     return move_dex(arg[0], arg[1]); /* src, dst */
  43 }
                        :

  50 static int do_remove(char **arg, char reply[REPLY_MAX])
  51 {
  52     return uninstall(arg[0], atoi(arg[1])); /* pkgname, userid */
  53 }
                        :

     // 「コマンド名→関数名」のテーブル
 125 struct cmdinfo {
 126     const char *name;
 127     unsigned numargs;
 128     int (*func)(char **arg, char reply[REPLY_MAX]);
 129 };
 130 
 131 struct cmdinfo cmds[] = {
 132     { "ping",                 0, do_ping },
 133     { "install",              3, do_install },
 134     { "dexopt",               3, do_dexopt },
 135     { "movedex",              2, do_move_dex },
 136     { "rmdex",                1, do_rm_dex },
 137     { "remove",               2, do_remove },
 138     { "rename",               2, do_rename },
 139     { "freecache",            1, do_free_cache },
 140     { "rmcache",              1, do_rm_cache },
 141     { "protect",              2, do_protect },
 142     { "getsize",              4, do_get_size },
 143     { "rmuserdata",           2, do_rm_user_data },
 144     { "movefiles",            0, do_movefiles },
 145     { "linklib",              2, do_linklib },
 146     { "unlinklib",            1, do_unlinklib },
 147     { "mkuserdata",           3, do_mk_user_data },
 148     { "rmuser",               1, do_rm_user },
 149 };
                        :

 347 int main(const int argc, const char *argv[]) {
 348     char buf[BUFFER_MAX];
 349     struct sockaddr addr;
 350     socklen_t alen;
 351     int lsocket, s, count;
 352 
 353     if (initialize_globals() < 0) {
 354         ALOGE("Could not initialize globals; exiting.\n");
 355         exit(1);
 356     }
 357 
 358     if (initialize_directories() < 0) {
 359         ALOGE("Could not create directories; exiting.\n");
 360         exit(1);
 361     }
 362 
 363     lsocket = android_get_control_socket(SOCKET_PATH);
 364     if (lsocket < 0) {
 365         ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
 366         exit(1);
 367     }
 368     if (listen(lsocket, 5)) {
 369         ALOGE("Listen on socket failed: %s\n", strerror(errno));
 370         exit(1);
 371     }
 372     fcntl(lsocket, F_SETFD, FD_CLOEXEC);
 373 
         // /dev/socket/installd からの読み込みとコマンド呼び出し
 374     for (;;) {
 375         alen = sizeof(addr);
 376         s = accept(lsocket, &addr, &alen);
 377         if (s < 0) {
 378             ALOGE("Accept failed: %s\n", strerror(errno));
 379             continue;
 380         }
 381         fcntl(s, F_SETFD, FD_CLOEXEC);
 382 
 383         ALOGI("new connection\n");
 384         for (;;) {
 385             unsigned short count;
 386             if (readx(s, &count, sizeof(count))) {
 387                 ALOGE("failed to read size\n");
 388                 break;
 389             }
 390             if ((count < 1) || (count >= BUFFER_MAX)) {
 391                 ALOGE("invalid size %d\n", count);
 392                 break;
 393             }
 394             if (readx(s, buf, count)) {
 395                 ALOGE("failed to read command\n");
 396                 break;
 397             }
 398             buf[count] = 0;
 399             if (execute(s, buf)) break;
 400         }
 401         ALOGI("closing connection\n");
 402         close(s);
 403     }
 404 
 405     return 0;
 406 }
platform/frameworks/base/cmds/installd/commands.c より
installd デーモン 各コマンド関数の実体

  17 #include "installd.h"
                       :

  31 int install(const char *pkgname, uid_t uid, gid_t gid)
  32 {
  33     char pkgdir[PKG_PATH_MAX];
  34     char libdir[PKG_PATH_MAX];
  35 
  36     if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
  37         ALOGE("invalid uid/gid: %d %d\n", uid, gid);
  38         return -1;
  39     }
  40 
  41     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
  42         ALOGE("cannot create package path\n");
  43         return -1;
  44     }
  45 
  46     if (create_pkg_path(libdir, pkgname, PKG_LIB_POSTFIX, 0)) {
  47         ALOGE("cannot create package lib path\n");
  48         return -1;
  49     }
  50 
  51     if (mkdir(pkgdir, 0751) < 0) {
  52         ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
  53         return -errno;
  54     }
  55     if (chmod(pkgdir, 0751) < 0) {
  56         ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
  57         unlink(pkgdir);
  58         return -errno;
  59     }
  60     if (chown(pkgdir, uid, gid) < 0) {
  61         ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
  62         unlink(pkgdir);
  63         return -errno;
  64     }
  65 
  66 #ifdef HAVE_SELINUX
  67     if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
  68         LOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
  69         unlink(pkgdir);
  70         return -errno;
  71     }
  72 #endif
  73 
  74     if (mkdir(libdir, 0755) < 0) {
  75         ALOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
  76         unlink(pkgdir);
  77         return -errno;
  78     }
  79     if (chmod(libdir, 0755) < 0) {
  80         ALOGE("cannot chmod dir '%s': %s\n", libdir, strerror(errno));
  81         unlink(libdir);
  82         unlink(pkgdir);
  83         return -errno;
  84     }
  85     if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
  86         ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
  87         unlink(libdir);
  88         unlink(pkgdir);
  89         return -errno;
  90     }
  91 
  92 #ifdef HAVE_SELINUX
  93     if (selinux_android_setfilecon(libdir, pkgname, AID_SYSTEM) < 0) {
  94         LOGE("cannot setfilecon dir '%s': %s\n", libdir, strerror(errno));
  95         unlink(libdir);
  96         unlink(pkgdir);
  97         return -errno;
  98     }
  99 #endif
 100 
 101     return 0;
 102 }
 103 
 104 int uninstall(const char *pkgname, uid_t persona)
 105 {
 106     char pkgdir[PKG_PATH_MAX];
 107 
 108     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona))
 109         return -1;
 110 
 111     /* delete contents AND directory, no exceptions */
 112     return delete_dir_contents(pkgdir, 1, NULL);
 113 }
                   :

 267 int move_dex(const char *src, const char *dst)
 268 {
 269     char src_dex[PKG_PATH_MAX];
 270     char dst_dex[PKG_PATH_MAX];
 271 
 272     if (validate_apk_path(src)) return -1;
 273     if (validate_apk_path(dst)) return -1;
 274 
 275     if (create_cache_path(src_dex, src)) return -1;
 276     if (create_cache_path(dst_dex, dst)) return -1;
 277 
 278     ALOGV("move %s -> %s\n", src_dex, dst_dex);
 279     if (rename(src_dex, dst_dex) < 0) {
 280         ALOGE("Couldn't move %s: %s\n", src_dex, strerror(errno));
 281         return -1;
 282     } else {
 283         return 0;
 284     }
 285 }

 471 static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,
 472     const char* dexopt_flags)
 473 {
         // Android 標準の dexopt コマンドを利用
 474     static const char* DEX_OPT_BIN = "/system/bin/dexopt";
 475     static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
 476     char zip_num[MAX_INT_LEN];
 477     char odex_num[MAX_INT_LEN];
 478 
 479     sprintf(zip_num, "%d", zip_fd);
 480     sprintf(odex_num, "%d", odex_fd);
 481 
 482     execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name,
 483         dexopt_flags, (char*) NULL);
 484     ALOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
 485 }
 486 
 487 static int wait_dexopt(pid_t pid, const char* apk_path)
 488 {
 489     int status;
 490     pid_t got_pid;
 491 
 492     /*
 493      * Wait for the optimization process to finish.
 494      */
 495     while (1) {
 496         got_pid = waitpid(pid, &status, 0);
 497         if (got_pid == -1 && errno == EINTR) {
 498             printf("waitpid interrupted, retrying\n");
 499         } else {
 500             break;
 501         }
 502     }
 503     if (got_pid != pid) {
 504         ALOGW("waitpid failed: wanted %d, got %d: %s\n",
 505             (int) pid, (int) got_pid, strerror(errno));
 506         return 1;
 507     }
 508 
 509     if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
 510         ALOGV("DexInv: --- END '%s' (success) ---\n", apk_path);
 511         return 0;
 512     } else {
 513         ALOGW("DexInv: --- END '%s' --- status=0x%04x, process failed\n",
 514             apk_path, status);
 515         return status;      /* always nonzero */
 516     }
 517 }
 518 
 519 int dexopt(const char *apk_path, uid_t uid, int is_public)
 520 {
 521     struct utimbuf ut;
 522     struct stat apk_stat, dex_stat;
 523     char dex_path[PKG_PATH_MAX];
 524     char dexopt_flags[PROPERTY_VALUE_MAX];
 525     char *end;
 526     int res, zip_fd=-1, odex_fd=-1;
 527 
 528         /* Before anything else: is there a .odex file?  If so, we have
 529          * pre-optimized the apk and there is nothing to do here.
 530          */
 531     if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
 532         return -1;
 533     }
 534 
 535     /* platform-specific flags affecting optimization and verification */
 536     property_get("dalvik.vm.dexopt-flags", dexopt_flags, "");
 537 
 538     strcpy(dex_path, apk_path);
 539     end = strrchr(dex_path, '.');
 540     if (end != NULL) {
 541         strcpy(end, ".odex");
 542         if (stat(dex_path, &dex_stat) == 0) {
 543             return 0;
 544         }
 545     }
 546 
 547     if (create_cache_path(dex_path, apk_path)) {
 548         return -1;
 549     }
 550 
 551     memset(&apk_stat, 0, sizeof(apk_stat));
 552     stat(apk_path, &apk_stat);
 553 
 554     zip_fd = open(apk_path, O_RDONLY, 0);
 555     if (zip_fd < 0) {
 556         ALOGE("dexopt cannot open '%s' for input\n", apk_path);
 557         return -1;
 558     }
 559 
 560     unlink(dex_path);
 561     odex_fd = open(dex_path, O_RDWR | O_CREAT | O_EXCL, 0644);
 562     if (odex_fd < 0) {
 563         ALOGE("dexopt cannot open '%s' for output\n", dex_path);
 564         goto fail;
 565     }
 566     if (fchown(odex_fd, AID_SYSTEM, uid) < 0) {
 567         ALOGE("dexopt cannot chown '%s'\n", dex_path);
 568         goto fail;
 569     }
 570     if (fchmod(odex_fd,
 571                S_IRUSR|S_IWUSR|S_IRGRP |
 572                (is_public ? S_IROTH : 0)) < 0) {
 573         ALOGE("dexopt cannot chmod '%s'\n", dex_path);
 574         goto fail;
 575     }
 576 
 577     ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path);
 578 
 579     pid_t pid;
 580     pid = fork();
 581     if (pid == 0) {
 582         /* child -- drop privileges before continuing */
 583         if (setgid(uid) != 0) {
 584             ALOGE("setgid(%d) failed during dexopt\n", uid);
 585             exit(64);
 586         }
 587         if (setuid(uid) != 0) {
 588             ALOGE("setuid(%d) during dexopt\n", uid);
 589             exit(65);
 590         }
 591         if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) {
 592             ALOGE("flock(%s) failed: %s\n", dex_path, strerror(errno));
 593             exit(66);
 594         }
 595 
 596         run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags);
 597         exit(67);   /* only get here on exec failure */
 598     } else {
 599         res = wait_dexopt(pid, apk_path);
 600         if (res != 0) {
 601             ALOGE("dexopt failed on '%s' res = %d\n", dex_path, res);
 602             goto fail;
 603         }
 604     }
 605 
 606     ut.actime = apk_stat.st_atime;
 607     ut.modtime = apk_stat.st_mtime;
 608     utime(dex_path, &ut);
 609     
 610     close(odex_fd);
 611     close(zip_fd);
 612     return 0;
 613 
 614 fail:
 615     if (odex_fd >= 0) {
 616         close(odex_fd);
 617         unlink(dex_path);
 618     }
 619     if (zip_fd >= 0) {
 620         close(zip_fd);
 621     }
 622     return -1;
 623 }
 624 
                :

Settings クラス コンストラクタ

frameworks/base/services/java/com/android/server/pm/Settings.java より

Settings クラス  パッケージまわりの情報を管理するクラス

  17 package com.android.server.pm;
                    :

  68 /**
  69  * Holds information about dynamic settings.
  70  */
  71 final class Settings {
  72     private static final String TAG = "PackageSettings";
  73 
  74     private static final boolean DEBUG_STOPPED = false;
  75 
  76     private final File mSettingsFilename;
  77     private final File mBackupSettingsFilename;
  78     private final File mPackageListFilename;
  79     private final File mStoppedPackagesFilename;
  80     private final File mBackupStoppedPackagesFilename;
  81     final HashMap<String, PackageSetting> mPackages =
  82             new HashMap<String, PackageSetting>();
  83     // List of replaced system applications
  84     final HashMap<String, PackageSetting> mDisabledSysPackages =
  85         new HashMap<String, PackageSetting>();
  86 
  87     // These are the last platform API version we were using for
  88     // the apps installed on internal and external storage.  It is
  89     // used to grant newer permissions one time during a system upgrade.
  90     int mInternalSdkPlatform;
  91     int mExternalSdkPlatform;
  92 
  93     /** Device identity for the purpose of package verification. */
  94     private VerifierDeviceIdentity mVerifierDeviceIdentity;
  95 
  96     // The user's preferred activities associated with particular intent
  97     // filters.
  98     final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
  99                 new IntentResolver<PreferredActivity, PreferredActivity>() {
 100         @Override
 101         protected String packageForFilter(PreferredActivity filter) {
 102             return filter.mPref.mComponent.getPackageName();
 103         }
 104         @Override
 105         protected void dumpFilter(PrintWriter out, String prefix,
 106                 PreferredActivity filter) {
 107             filter.mPref.dump(out, prefix, filter);
 108         }
 109     };
 110     final HashMap<String, SharedUserSetting> mSharedUsers =
 111             new HashMap<String, SharedUserSetting>();
 112     private final ArrayList<Object> mUserIds = new ArrayList<Object>();
 113     private final SparseArray<Object> mOtherUserIds =
 114             new SparseArray<Object>();
 115 
 116     // For reading/writing settings file.
 117     private final ArrayList<Signature> mPastSignatures =
 118             new ArrayList<Signature>();
 119 
 120     // Mapping from permission names to info about them.
 121     final HashMap<String, BasePermission> mPermissions =
 122             new HashMap<String, BasePermission>();
 123 
 124     // Mapping from permission tree names to info about them.
 125     final HashMap<String, BasePermission> mPermissionTrees =
 126             new HashMap<String, BasePermission>();
 127 
 128     // Packages that have been uninstalled and still need their external
 129     // storage data deleted.
 130     final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
 131     
 132     // Packages that have been renamed since they were first installed.
 133     // Keys are the new names of the packages, values are the original
 134     // names.  The packages appear everwhere else under their original
 135     // names.
 136     final HashMap<String, String> mRenamedPackages = new HashMap<String, String>();
 137     
 138     final StringBuilder mReadMessages = new StringBuilder();
 139 
 140     /**
 141      * Used to track packages that have a shared user ID that hasn't been read
 142      * in yet.
 143      * <p>
 144      * TODO: make this just a local variable that is passed in during package
 145      * scanning to make it less confusing.
 146      */
 147     private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>();
 148 

         // コンストラクタ
 149     Settings() {
 150         File dataDir = Environment.getDataDirectory();
 151         File systemDir = new File(dataDir, "system");
 152         systemDir.mkdirs();
 153         FileUtils.setPermissions(systemDir.toString(),
 154                 FileUtils.S_IRWXU|FileUtils.S_IRWXG
 155                 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
 156                 -1, -1);
 157         mSettingsFilename = new File(systemDir, "packages.xml");
 158         mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
 159         mPackageListFilename = new File(systemDir, "packages.list");
 160         mStoppedPackagesFilename = new File(systemDir, "packages-stopped.xml");
 161         mBackupStoppedPackagesFilename = new File(systemDir, "packages-stopped-backup.xml");
 162     }
                     :

PackageManagerService.readPermissions()

frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より

1236     void readPermissions() {
1237         // Read permissions from .../etc/permission directory.
             // "/system/etc/permissions"
1238         File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
1239         if (!libraryDir.exists() || !libraryDir.isDirectory()) {
1240             Slog.w(TAG, "No directory " + libraryDir + ", skipping");
1241             return;
1242         }
1243         if (!libraryDir.canRead()) {
1244             Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
1245             return;
1246         }
1247 
1248         // Iterate over the files in the directory and scan .xml files
1249         for (File f : libraryDir.listFiles()) {
                 // platform.xml は後回し
1250             // We'll read platform.xml last
1251             if (f.getPath().endsWith("etc/permissions/platform.xml")) {
1252                 continue;
1253             }
1254 
1255             if (!f.getPath().endsWith(".xml")) {
1256                 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
1257                 continue;
1258             }
1259             if (!f.canRead()) {
1260                 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
1261                 continue;
1262             }
1263 
1264             readPermissionsFromXml(f);
1265         }
1266         // 最後に platform.xml を処理
1267         // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
1268         final File permFile = new File(Environment.getRootDirectory(),
1269                 "etc/permissions/platform.xml");
1270         readPermissionsFromXml(permFile);
1271     }
1272 
1273     private void readPermissionsFromXml(File permFile) {
1274         FileReader permReader = null;
1275         try {
1276             permReader = new FileReader(permFile);
1277         } catch (FileNotFoundException e) {
1278             Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
1279             return;
1280         }
1281 
1282         try {
1283             XmlPullParser parser = Xml.newPullParser();
1284             parser.setInput(permReader);
1285 
1286             XmlUtils.beginDocument(parser, "permissions");
1287 
1288             while (true) {
1289                 XmlUtils.nextElement(parser);
1290                 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
1291                     break;
1292                 }
1293 
1294                 String name = parser.getName();
1295                 if ("group".equals(name)) {
1296                     String gidStr = parser.getAttributeValue(null, "gid");
1297                     if (gidStr != null) {
1298                         int gid = Integer.parseInt(gidStr);
1299                         mGlobalGids = appendInt(mGlobalGids, gid);
1300                     } else {
1301                         Slog.w(TAG, " without gid at "
1302                                 + parser.getPositionDescription());
1303                     }
1304 
1305                     XmlUtils.skipCurrentTag(parser);
1306                     continue;
1307                 } else if ("permission".equals(name)) {
                            :

Settings.readLPw() / Settings.writeLPr()

frameworks/base/services/java/com/android/server/pm/Settings.java より


         // /data/system/packages.xml よりパッケージまわりの情報をロード
1196     boolean readLPw() {
1197         FileInputStream str = null;
1198         if (mBackupSettingsFilename.exists()) {
1199             try {
1200                 str = new FileInputStream(mBackupSettingsFilename);
1201                 mReadMessages.append("Reading from backup settings file\n");
1202                 PackageManagerService.reportSettingsProblem(Log.INFO,
1203                         "Need to read from backup settings file");
1204                 if (mSettingsFilename.exists()) {
1205                     // If both the backup and settings file exist, we
1206                     // ignore the settings since it might have been
1207                     // corrupted.
1208                     Slog.w(PackageManagerService.TAG, "Cleaning up settings file "
1209                             + mSettingsFilename);
1210                     mSettingsFilename.delete();
1211                 }
1212             } catch (java.io.IOException e) {
1213                 // We'll try for the normal settings file.
1214             }
1215         }
1216 
1217         mPendingPackages.clear();
1218         mPastSignatures.clear();
1219 
1220         try {
1221             if (str == null) {
1222                 if (!mSettingsFilename.exists()) {
1223                     mReadMessages.append("No settings file found\n");
1224                     PackageManagerService.reportSettingsProblem(Log.INFO,
1225                             "No settings file; creating initial state");
1226                     return false;
1227                 }
1228                 str = new FileInputStream(mSettingsFilename);
1229             }
1230             XmlPullParser parser = Xml.newPullParser();
1231             parser.setInput(str, null);
1232 
1233             int type;
1234             while ((type = parser.next()) != XmlPullParser.START_TAG
1235                     && type != XmlPullParser.END_DOCUMENT) {
1236                 ;
1237             }
1238 
1239             if (type != XmlPullParser.START_TAG) {
1240                 mReadMessages.append("No start tag found in settings file\n");
1241                 PackageManagerService.reportSettingsProblem(Log.WARN,
1242                         "No start tag found in package manager settings");
1243                 Log.wtf(PackageManagerService.TAG,
1244                         "No start tag found in package manager settings");
1245                 return false;
1246             }
1247 
1248             int outerDepth = parser.getDepth();
1249             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1250                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1251                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1252                     continue;
1253                 }
1254
1255                 String tagName = parser.getName();
1256                 if (tagName.equals("package")) {
1257                     readPackageLPw(parser);
1258                 } else if (tagName.equals("permissions")) {
1259                     readPermissionsLPw(mPermissions, parser);
1260                 } else if (tagName.equals("permission-trees")) {
1261                     readPermissionsLPw(mPermissionTrees, parser);
1262                 } else if (tagName.equals("shared-user")) {
1263                     readSharedUserLPw(parser);
1264                 } else if (tagName.equals("preferred-packages")) {
1265                     // no longer used.
1266                 } else if (tagName.equals("preferred-activities")) {
1267                     readPreferredActivitiesLPw(parser);
1268                 } else if (tagName.equals("updated-package")) {
1269                     readDisabledSysPackageLPw(parser);
1270                 } else if (tagName.equals("cleaning-package")) {
1271                     String name = parser.getAttributeValue(null, "name");
1272                     if (name != null) {
1273                         mPackagesToBeCleaned.add(name);
1274                     }
1275                 } else if (tagName.equals("renamed-package")) {
1276                     String nname = parser.getAttributeValue(null, "new");
1277                     String oname = parser.getAttributeValue(null, "old");
1278                     if (nname != null && oname != null) {
1279                         mRenamedPackages.put(nname, oname);
1280                     }
1281                 } else if (tagName.equals("last-platform-version")) {
1282                     mInternalSdkPlatform = mExternalSdkPlatform = 0;
1283                     try {
1284                         String internal = parser.getAttributeValue(null, "internal");
1285                         if (internal != null) {
1286                             mInternalSdkPlatform = Integer.parseInt(internal);
1287                         }
1288                         String external = parser.getAttributeValue(null, "external");
1289                         if (external != null) {
1290                             mExternalSdkPlatform = Integer.parseInt(external);
1291                         }
1292                     } catch (NumberFormatException e) {
1293                     }
1294                 } else if (tagName.equals("verifier")) {
1295                     final String deviceIdentity = parser.getAttributeValue(null, "device");
1296                     try {
1297                         mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
1298                     } catch (IllegalArgumentException e) {
1299                         Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
1300                                 + e.getMessage());
1301                     }
1302                 } else {
1303                     Slog.w(PackageManagerService.TAG, "Unknown element under : "
1304                             + parser.getName());
1305                     XmlUtils.skipCurrentTag(parser);
1306                 } 
1307             }
1308 
1309             str.close();
1310 
1311         } catch (XmlPullParserException e) {
1312             mReadMessages.append("Error reading: " + e.toString());
1313             PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
1314             Log.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
1315 
1316         } catch (java.io.IOException e) {
1317             mReadMessages.append("Error reading: " + e.toString());
1318             PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
1319             Log.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
1320 
1321         }
1322 
1323         final int N = mPendingPackages.size();
1324         for (int i = 0; i < N; i++) {
1325             final PendingPackage pp = mPendingPackages.get(i);
1326             Object idObj = getUserIdLPr(pp.sharedId);
1327             if (idObj != null && idObj instanceof SharedUserSetting) {
1328                 PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
1329                         (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
1330                         pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags, true, true);
1331                 if (p == null) {
1332                     PackageManagerService.reportSettingsProblem(Log.WARN,
1333                             "Unable to create application package for " + pp.name);
1334                     continue;
1335                 }
1336                 p.copyFrom(pp);
1337             } else if (idObj != null) {
1338                 String msg = "Bad package setting: package " + pp.name + " has shared uid "
1339                         + pp.sharedId + " that is not a shared uid\n";
1340                 mReadMessages.append(msg);
1341                 PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
1342             } else {
1343                 String msg = "Bad package setting: package " + pp.name + " has shared uid "
1344                         + pp.sharedId + " that is not defined\n";
1345                 mReadMessages.append(msg);
1346                 PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
1347             }
1348         }
1349         mPendingPackages.clear();
1350 
1351         /*
1352          * Make sure all the updated system packages have their shared users
1353          * associated with them.
1354          */
1355         final Iterator disabledIt = mDisabledSysPackages.values().iterator();
1356         while (disabledIt.hasNext()) {
1357             final PackageSetting disabledPs = disabledIt.next();
1358             final Object id = getUserIdLPr(disabledPs.userId);
1359             if (id != null && id instanceof SharedUserSetting) {
1360                 disabledPs.sharedUser = (SharedUserSetting) id;
1361             }
1362         }
1363 
1364         readStoppedLPw();
1365 
1366         mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
1367                 + mSharedUsers.size() + " shared uids\n");
1368 
1369         return true;
1370     }
                           :


         // /data/system/packages.xml, packages.list へパッケージまわりの情報を保存
 833     void writeLPr() {
 834         //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
 835 
 836         // Keep the old settings around until we know the new ones have
 837         // been successfully written.
 838         if (mSettingsFilename.exists()) {
 839             // Presence of backup settings file indicates that we failed
 840             // to persist settings earlier. So preserve the older
 841             // backup for future reference since the current settings
 842             // might have been corrupted.
 843             if (!mBackupSettingsFilename.exists()) {
 844                 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
 845                     Log.wtf(PackageManagerService.TAG, "Unable to backup package manager settings, "
 846                             + " current changes will be lost at reboot");
 847                     return;
 848                 }
 849             } else {
 850                 mSettingsFilename.delete();
 851                 Slog.w(PackageManagerService.TAG, "Preserving older settings backup");
 852             }
 853         }
 854 
 855         mPastSignatures.clear();
 856 
 857         try {
 858             FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
 859             BufferedOutputStream str = new BufferedOutputStream(fstr);
 860 
 861             //XmlSerializer serializer = XmlUtils.serializerInstance();
 862             XmlSerializer serializer = new FastXmlSerializer();
 863             serializer.setOutput(str, "utf-8");
 864             serializer.startDocument(null, true);
 865             serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
 866 
 867             serializer.startTag(null, "packages");
 868 
 869             serializer.startTag(null, "last-platform-version");
 870             serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
 871             serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
 872             serializer.endTag(null, "last-platform-version");
 873             
 874             if (mVerifierDeviceIdentity != null) {
 875                 serializer.startTag(null, "verifier");
 876                 serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
 877                 serializer.endTag(null, "verifier");
 878             }
 879 
 880             serializer.startTag(null, "permission-trees");
 881             for (BasePermission bp : mPermissionTrees.values()) {
 882                 writePermissionLPr(serializer, bp);
 883             }
 884             serializer.endTag(null, "permission-trees");
 885 
 886             serializer.startTag(null, "permissions");
 887             for (BasePermission bp : mPermissions.values()) {
 888                 writePermissionLPr(serializer, bp);
 889             }
 890             serializer.endTag(null, "permissions");
 891 
 892             for (final PackageSetting pkg : mPackages.values()) {
 893                 writePackageLPr(serializer, pkg);
 894             }
 895 
 896             for (final PackageSetting pkg : mDisabledSysPackages.values()) {
 897                 writeDisabledSysPackageLPr(serializer, pkg);
 898             }
 899 
 900             serializer.startTag(null, "preferred-activities");
 901             for (final PreferredActivity pa : mPreferredActivities.filterSet()) {
 902                 serializer.startTag(null, "item");
 903                 pa.writeToXml(serializer);
 904                 serializer.endTag(null, "item");
 905             }
 906             serializer.endTag(null, "preferred-activities");
 907 
 908             for (final SharedUserSetting usr : mSharedUsers.values()) {
 909                 serializer.startTag(null, "shared-user");
 910                 serializer.attribute(null, "name", usr.name);
 911                 serializer.attribute(null, "userId",
 912                         Integer.toString(usr.userId));
 913                 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
 914                 serializer.startTag(null, "perms");
 915                 for (String name : usr.grantedPermissions) {
 916                     serializer.startTag(null, "item");
 917                     serializer.attribute(null, "name", name);
 918                     serializer.endTag(null, "item");
 919                 }
 920                 serializer.endTag(null, "perms");
 921                 serializer.endTag(null, "shared-user");
 922             }
 923 
 924             if (mPackagesToBeCleaned.size() > 0) {
 925                 for (int i=0; i 0) {
 933                 for (HashMap.Entry e : mRenamedPackages.entrySet()) {
 934                     serializer.startTag(null, "renamed-package");
 935                     serializer.attribute(null, "new", e.getKey());
 936                     serializer.attribute(null, "old", e.getValue());
 937                     serializer.endTag(null, "renamed-package");
 938                 }
 939             }
 940             
 941             serializer.endTag(null, "packages");
 942 
 943             serializer.endDocument();
 944 
 945             str.flush();
 946             FileUtils.sync(fstr);
 947             str.close();
 948 
 949             // New settings successfully written, old ones are no longer
 950             // needed.
 951             mBackupSettingsFilename.delete();
 952             FileUtils.setPermissions(mSettingsFilename.toString(),
 953                     FileUtils.S_IRUSR|FileUtils.S_IWUSR
 954                     |FileUtils.S_IRGRP|FileUtils.S_IWGRP
 955                     |FileUtils.S_IROTH,
 956                     -1, -1);
 957 
 958             // Write package list file now, use a JournaledFile.
 959             //
 960             File tempFile = new File(mPackageListFilename.toString() + ".tmp");
 961             JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
 962 
 963             fstr = new FileOutputStream(journal.chooseForWrite());
 964             str = new BufferedOutputStream(fstr);
 965             try {
 966                 StringBuilder sb = new StringBuilder();
 967                 for (final PackageSetting pkg : mPackages.values()) {
 968                     ApplicationInfo ai = pkg.pkg.applicationInfo;
 969                     String dataPath = ai.dataDir;
 970                     boolean isDebug  = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
 971 
 972                     // Avoid any application that has a space in its path
 973                     // or that is handled by the system.
 974                     if (dataPath.indexOf(" ") >= 0 || ai.uid < Process.FIRST_APPLICATION_UID)
 975                         continue;
 976 
 977                     // we store on each line the following information for now:
 978                     //
 979                     // pkgName    - package name
 980                     // userId     - application-specific user id
 981                     // debugFlag  - 0 or 1 if the package is debuggable.
 982                     // dataPath   - path to package's data path
 983                     //
 984                     // NOTE: We prefer not to expose all ApplicationInfo flags for now.
 985                     //
 986                     // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
 987                     // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
 988                     //   system/core/run-as/run-as.c
 989                     //
 990                     sb.setLength(0);
 991                     sb.append(ai.packageName);
 992                     sb.append(" ");
 993                     sb.append((int)ai.uid);
 994                     sb.append(isDebug ? " 1 " : " 0 ");
 995                     sb.append(dataPath);
 996                     sb.append("\n");
 997                     str.write(sb.toString().getBytes());
 998                 }
 999                 str.flush();
1000                 FileUtils.sync(fstr);
1001                 str.close();
1002                 journal.commit();
1003             } catch (Exception e) {
1004                 IoUtils.closeQuietly(str);
1005                 journal.rollback();
1006             }
1007 
1008             FileUtils.setPermissions(mPackageListFilename.toString(),
1009                     FileUtils.S_IRUSR|FileUtils.S_IWUSR
1010                     |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1011                     |FileUtils.S_IROTH,
1012                     -1, -1);
1013 
1014             writeStoppedLPr();
1015 
1016             return;
1017 
1018         } catch(XmlPullParserException e) {
1019             Log.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
1020                     + "current changes will be lost at reboot", e);
1021         } catch(java.io.IOException e) {
1022             Log.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
1023                     + "current changes will be lost at reboot", e);
1024         }
1025         // Clean up partially written files
1026         if (mSettingsFilename.exists()) {
1027             if (!mSettingsFilename.delete()) {
1028                 Log.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: " + mSettingsFilename);
1029             }
1030         }
1031         //Debug.stopMethodTracing();
1032     }
1033 
1034     void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg)
1035             throws java.io.IOException {
1036         serializer.startTag(null, "updated-package");
1037         serializer.attribute(null, "name", pkg.name);
1038         if (pkg.realName != null) {
1039             serializer.attribute(null, "realName", pkg.realName);
1040         }
1041         serializer.attribute(null, "codePath", pkg.codePathString);
1042         serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
1043         serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
1044         serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
1045         serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
1046         if (!pkg.resourcePathString.equals(pkg.codePathString)) {
1047             serializer.attribute(null, "resourcePath", pkg.resourcePathString);
1048         }
1049         if (pkg.nativeLibraryPathString != null) {
1050             serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
1051         }
1052         if (pkg.sharedUser == null) {
1053             serializer.attribute(null, "userId", Integer.toString(pkg.userId));
1054         } else {
1055             serializer.attribute(null, "sharedUserId", Integer.toString(pkg.userId));
1056         }
1057         serializer.startTag(null, "perms");
1058         if (pkg.sharedUser == null) {
1059             // If this is a shared user, the permissions will
1060             // be written there. We still need to write an
1061             // empty permissions list so permissionsFixed will
1062             // be set.
1063             for (final String name : pkg.grantedPermissions) {
1064                 BasePermission bp = mPermissions.get(name);
1065                 if (bp != null) {
1066                     // We only need to write signature or system permissions but
1067                     // this wont
1068                     // match the semantics of grantedPermissions. So write all
1069                     // permissions.
1070                     serializer.startTag(null, "item");
1071                     serializer.attribute(null, "name", name);
1072                     serializer.endTag(null, "item");
1073                 }
1074             }
1075         }
1076         serializer.endTag(null, "perms");
1077         serializer.endTag(null, "updated-package");
1078     }
1079 
1080     void writePackageLPr(XmlSerializer serializer, final PackageSetting pkg)
1081             throws java.io.IOException {
1082         serializer.startTag(null, "package");
1083         serializer.attribute(null, "name", pkg.name);
1084         if (pkg.realName != null) {
1085             serializer.attribute(null, "realName", pkg.realName);
1086         }
1087         serializer.attribute(null, "codePath", pkg.codePathString);
1088         if (!pkg.resourcePathString.equals(pkg.codePathString)) {
1089             serializer.attribute(null, "resourcePath", pkg.resourcePathString);
1090         }
1091         if (pkg.nativeLibraryPathString != null) {
1092             serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
1093         }
1094         serializer.attribute(null, "flags", Integer.toString(pkg.pkgFlags));
1095         serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
1096         serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
1097         serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
1098         serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
1099         if (pkg.sharedUser == null) {
1100             serializer.attribute(null, "userId", Integer.toString(pkg.userId));
1101         } else {
1102             serializer.attribute(null, "sharedUserId", Integer.toString(pkg.userId));
1103         }
1104         if (pkg.uidError) {
1105             serializer.attribute(null, "uidError", "true");
1106         }
1107         if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
1108             serializer.attribute(null, "enabled", Integer.toString(pkg.enabled));
1109         }
1110         if (pkg.installStatus == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
1111             serializer.attribute(null, "installStatus", "false");
1112         }
1113         if (pkg.installerPackageName != null) {
1114             serializer.attribute(null, "installer", pkg.installerPackageName);
1115         }
1116         pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
1117         if ((pkg.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
1118             serializer.startTag(null, "perms");
1119             if (pkg.sharedUser == null) {
1120                 // If this is a shared user, the permissions will
1121                 // be written there. We still need to write an
1122                 // empty permissions list so permissionsFixed will
1123                 // be set.
1124                 for (final String name : pkg.grantedPermissions) {
1125                     serializer.startTag(null, "item");
1126                     serializer.attribute(null, "name", name);
1127                     serializer.endTag(null, "item");
1128                 }
1129             }
1130             serializer.endTag(null, "perms");
1131         }
1132         if (pkg.disabledComponents.size() > 0) {
1133             serializer.startTag(null, "disabled-components");
1134             for (final String name : pkg.disabledComponents) {
1135                 serializer.startTag(null, "item");
1136                 serializer.attribute(null, "name", name);
1137                 serializer.endTag(null, "item");
1138             }
1139             serializer.endTag(null, "disabled-components");
1140         }
1141         if (pkg.enabledComponents.size() > 0) {
1142             serializer.startTag(null, "enabled-components");
1143             for (final String name : pkg.enabledComponents) {
1144                 serializer.startTag(null, "item");
1145                 serializer.attribute(null, "name", name);
1146                 serializer.endTag(null, "item");
1147             }
1148             serializer.endTag(null, "enabled-components");
1149         }
1150 
1151         serializer.endTag(null, "package");
1152     }
1153 
1154     void writePermissionLPr(XmlSerializer serializer, BasePermission bp)
1155             throws XmlPullParserException, java.io.IOException {
1156         if (bp.type != BasePermission.TYPE_BUILTIN && bp.sourcePackage != null) {
1157             serializer.startTag(null, "item");
1158             serializer.attribute(null, "name", bp.name);
1159             serializer.attribute(null, "package", bp.sourcePackage);
1160             if (bp.protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
1161                 serializer.attribute(null, "protection", Integer.toString(bp.protectionLevel));
1162             }
1163             if (PackageManagerService.DEBUG_SETTINGS)
1164                 Log.v(PackageManagerService.TAG, "Writing perm: name=" + bp.name + " type="
1165                         + bp.type);
1166             if (bp.type == BasePermission.TYPE_DYNAMIC) {
1167                 final PermissionInfo pi = bp.perm != null ? bp.perm.info : bp.pendingInfo;
1168                 if (pi != null) {
1169                     serializer.attribute(null, "type", "dynamic");
1170                     if (pi.icon != 0) {
1171                         serializer.attribute(null, "icon", Integer.toString(pi.icon));
1172                     }
1173                     if (pi.nonLocalizedLabel != null) {
1174                         serializer.attribute(null, "label", pi.nonLocalizedLabel.toString());
1175                     }
1176                 }
1177             }
1178             serializer.endTag(null, "item");
1179         }
1180     }

PackageSignatures.writeXml()

frameworks/base/services/java/com/android/server/pm/PackageSignatures.java より

パッケージの署名を処理するクラス

  31 class PackageSignatures {
  32     Signature[] mSignatures;
  33 
  34     PackageSignatures(PackageSignatures orig) {
  35         if (orig != null && orig.mSignatures != null) {
  36             mSignatures = orig.mSignatures.clone();
  37         }
  38     }
  39 
  40     PackageSignatures(Signature[] sigs) {
  41         assignSignatures(sigs);
  42     }
  43 
  44     PackageSignatures() {
  45     }
  46 
  47     void writeXml(XmlSerializer serializer, String tagName,
  48             ArrayList<Signature> pastSignatures) throws IOException {
  49         if (mSignatures == null) {
  50             return;
  51         }
  52         serializer.startTag(null, tagName);
  53         serializer.attribute(null, "count",
  54                 Integer.toString(mSignatures.length));
  55         for (int i=0; i<mSignatures.length; i++) {
  56             serializer.startTag(null, "cert");
  57             final Signature sig = mSignatures[i];
  58             final int sigHash = sig.hashCode();
  59             final int numPast = pastSignatures.size();
  60             int j;
  61             for (j=0; j<numPast; j++) {
  62                 Signature pastSig = pastSignatures.get(j);

                     // 同一の key を出力ずみなら index のみを書き出す
  63                 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
  64                     serializer.attribute(null, "index", Integer.toString(j));
  65                     break;
  66                 }
  67             }
  68             if (j >= numPast) { // 初出分のみ index と key を書き出す
                     // ここで呼び元の Settings.mPastSignatures に add される
  69                 pastSignatures.add(sig);
  70                 serializer.attribute(null, "index", Integer.toString(numPast));
  71                 serializer.attribute(null, "key", sig.toCharsString());
  72             }
  73             serializer.endTag(null, "cert");
  74         }
  75         serializer.endTag(null, tagName);
  76     }
                       :

PreferredActivity.writeToXml()

frameworks/base/services/java/com/android/server/pm/PreferredActivity.java より

PreferredActivity クラス

  17 package com.android.server.pm;
                  :

  32 class PreferredActivity extends IntentFilter implements PreferredComponent.Callbacks {
  33     private static final String TAG = "PreferredActivity";
  34 
  35     private static final boolean DEBUG_FILTERS = false;
  36 
  37     final PreferredComponent mPref;
  38 
  39     PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
  40         super(filter);
  41         mPref = new PreferredComponent(this, match, set, activity);
  42     }
  43 
  44     PreferredActivity(XmlPullParser parser) throws XmlPullParserException, IOException {
  45         mPref = new PreferredComponent(this, parser);
  46     }
  47 
  48     public void writeToXml(XmlSerializer serializer) throws IOException {
  49         mPref.writeToXml(serializer);
  50         serializer.startTag(null, "filter");
  51         super.writeToXml(serializer);
  52         serializer.endTag(null, "filter");
  53     }
                      :

PreferredComponent.writeToXml()

frameworks/services/java/com/android/server/PreferredComponent.java より

PreferredComponent クラス

  17 package com.android.server;
                :

  35 public class PreferredComponent {
  36     public final int mMatch;
  37     public final ComponentName mComponent;
  38 
  39     private final String[] mSetPackages;
  40     private final String[] mSetClasses;
  41     private final String[] mSetComponents;
  42     private final String mShortComponent;
  43     private String mParseError;
  44 
  45     private final Callbacks mCallbacks;
  46 
  47     public interface Callbacks {
  48         public boolean onReadTag(String tagName, XmlPullParser parser)
  49                 throws XmlPullParserException, IOException;
  50     }
  51 
  52     public PreferredComponent(Callbacks callbacks, int match, ComponentName[] set,
  53             ComponentName component) {
  54         mCallbacks = callbacks;
  55         mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
  56         mComponent = component;
  57         mShortComponent = component.flattenToShortString();
  58         mParseError = null;
  59         if (set != null) {
  60             final int N = set.length;
  61             String[] myPackages = new String[N];
  62             String[] myClasses = new String[N];
  63             String[] myComponents = new String[N];
  64             for (int i=0; i<N; i++) {
  65                 ComponentName cn = set[i];
  66                 if (cn == null) {
  67                     mSetPackages = null;
  68                     mSetClasses = null;
  69                     mSetComponents = null;
  70                     return;
  71                 }
  72                 myPackages[i] = cn.getPackageName().intern();
  73                 myClasses[i] = cn.getClassName().intern();
  74                 myComponents[i] = cn.flattenToShortString().intern();
  75             }
  76             mSetPackages = myPackages;
  77             mSetClasses = myClasses;
  78             mSetComponents = myComponents;
  79         } else {
  80             mSetPackages = null;
  81             mSetClasses = null;
  82             mSetComponents = null;
  83         }
  84     }
  85 
  86     public PreferredComponent(Callbacks callbacks, XmlPullParser parser)
  87             throws XmlPullParserException, IOException {
  88         mCallbacks = callbacks;
  89         mShortComponent = parser.getAttributeValue(null, "name");
  90         mComponent = ComponentName.unflattenFromString(mShortComponent);
  91         if (mComponent == null) {
  92             mParseError = "Bad activity name " + mShortComponent;
  93         }
  94         String matchStr = parser.getAttributeValue(null, "match");
  95         mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
  96         String setCountStr = parser.getAttributeValue(null, "set");
  97         int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
  98 
  99         String[] myPackages = setCount > 0 ? new String[setCount] : null;
 100         String[] myClasses = setCount > 0 ? new String[setCount] : null;
 101         String[] myComponents = setCount > 0 ? new String[setCount] : null;
 102 
 103         int setPos = 0;
 104 
 105         int outerDepth = parser.getDepth();
 106         int type;
 107         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
 108                && (type != XmlPullParser.END_TAG
 109                        || parser.getDepth() > outerDepth)) {
 110             if (type == XmlPullParser.END_TAG
 111                     || type == XmlPullParser.TEXT) {
 112                 continue;
 113             }
 114 
 115             String tagName = parser.getName();
 116             //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
 117             //        + parser.getDepth() + " tag=" + tagName);
 118             if (tagName.equals("set")) {
 119                 String name = parser.getAttributeValue(null, "name");
 120                 if (name == null) {
 121                     if (mParseError == null) {
 122                         mParseError = "No name in set tag in preferred activity "
 123                             + mShortComponent;
 124                     }
 125                 } else if (setPos >= setCount) {
 126                     if (mParseError == null) {
 127                         mParseError = "Too many set tags in preferred activity "
 128                             + mShortComponent;
 129                     }
 130                 } else {
 131                     ComponentName cn = ComponentName.unflattenFromString(name);
 132                     if (cn == null) {
 133                         if (mParseError == null) {
 134                             mParseError = "Bad set name " + name + " in preferred activity "
 135                                 + mShortComponent;
 136                         }
 137                     } else {
 138                         myPackages[setPos] = cn.getPackageName();
 139                         myClasses[setPos] = cn.getClassName();
 140                         myComponents[setPos] = name;
 141                         setPos++;
 142                     }
 143                 }
 144                 XmlUtils.skipCurrentTag(parser);
 145             } else if (!mCallbacks.onReadTag(tagName, parser)) {
 146                 Slog.w("PreferredComponent", "Unknown element: " + parser.getName());
 147                 XmlUtils.skipCurrentTag(parser);
 148             }
 149         }
 150 
 151         if (setPos != setCount) {
 152             if (mParseError == null) {
 153                 mParseError = "Not enough set tags (expected " + setCount
 154                     + " but found " + setPos + ") in " + mShortComponent;
 155             }
 156         }
 157 
 158         mSetPackages = myPackages;
 159         mSetClasses = myClasses;
 160         mSetComponents = myComponents;
 161     }
 162 
 163     public String getParseError() {
 164         return mParseError;
 165     }
 166 
 167     public void writeToXml(XmlSerializer serializer) throws IOException {
 168         final int NS = mSetClasses != null ? mSetClasses.length : 0;
 169         serializer.attribute(null, "name", mShortComponent);
 170         if (mMatch != 0) {
 171             serializer.attribute(null, "match", Integer.toHexString(mMatch));
 172         }
 173         serializer.attribute(null, "set", Integer.toString(NS));
 174         for (int s=0; s<NS; s++) {
 175             serializer.startTag(null, "set");
 176             serializer.attribute(null, "name", mSetComponents[s]);
 177             serializer.endTag(null, "set");
 178         }
 179     }
                  :

IntentFilter.writeToXml()

/frameworks/core/java/android/content/IntentFilter.java より

IntentFilter クラス

  17 package android.content;
                :

 129 public class IntentFilter implements Parcelable {
 130     private static final String SGLOB_STR = "sglob";
 131     private static final String PREFIX_STR = "prefix";
 132     private static final String LITERAL_STR = "literal";
 133     private static final String PATH_STR = "path";
 134     private static final String PORT_STR = "port";
 135     private static final String HOST_STR = "host";
 136     private static final String AUTH_STR = "auth";
 137     private static final String SCHEME_STR = "scheme";
 138     private static final String TYPE_STR = "type";
 139     private static final String CAT_STR = "cat";
 140     private static final String NAME_STR = "name";
 141     private static final String ACTION_STR = "action";
 
                 :

1145     /**
1146      * Write the contents of the IntentFilter as an XML stream.
1147      */
1148     public void writeToXml(XmlSerializer serializer) throws IOException {
1149         int N = countActions();
1150         for (int i=0; i<N; i++) {
1151             serializer.startTag(null, ACTION_STR);
1152             serializer.attribute(null, NAME_STR, mActions.get(i));
1153             serializer.endTag(null, ACTION_STR);
1154         }
1155         N = countCategories();
1156         for (int i=0; i<N; i++) {
1157             serializer.startTag(null, CAT_STR);
1158             serializer.attribute(null, NAME_STR, mCategories.get(i));
1159             serializer.endTag(null, CAT_STR);
1160         }
1161         N = countDataTypes();
1162         for (int i=0; i<N; i++) {
1163             serializer.startTag(null, TYPE_STR);
1164             String type = mDataTypes.get(i);
1165             if (type.indexOf('/') < 0) type = type + "/*";
1166             serializer.attribute(null, NAME_STR, type);
1167             serializer.endTag(null, TYPE_STR);
1168         }
1169         N = countDataSchemes();
1170         for (int i=0; i<N; i++) {
1171             serializer.startTag(null, SCHEME_STR);
1172             serializer.attribute(null, NAME_STR, mDataSchemes.get(i));
1173             serializer.endTag(null, SCHEME_STR);
1174         }
1175         N = countDataAuthorities();
1176         for (int i=0; i<N; i++) {
1177             serializer.startTag(null, AUTH_STR);
1178             AuthorityEntry ae = mDataAuthorities.get(i);
1179             serializer.attribute(null, HOST_STR, ae.getHost());
1180             if (ae.getPort() >= 0) {
1181                 serializer.attribute(null, PORT_STR, Integer.toString(ae.getPort()));
1182             }
1183             serializer.endTag(null, AUTH_STR);
1184         }
1185         N = countDataPaths();
1186         for (int i=0; i<N; i++) {
1187             serializer.startTag(null, PATH_STR);
1188             PatternMatcher pe = mDataPaths.get(i);
1189             switch (pe.getType()) {
1190                 case PatternMatcher.PATTERN_LITERAL:
1191                     serializer.attribute(null, LITERAL_STR, pe.getPath());
1192                     break;
1193                 case PatternMatcher.PATTERN_PREFIX:
1194                     serializer.attribute(null, PREFIX_STR, pe.getPath());
1195                     break;
1196                 case PatternMatcher.PATTERN_SIMPLE_GLOB:
1197                     serializer.attribute(null, SGLOB_STR, pe.getPath());
1198                     break;
1199             }
1200             serializer.endTag(null, PATH_STR);
1201         }
1202     }
                 :

AppDirObserver によるインストール・アンインストールの自動処理

frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より

指定されたディレクトリ直下を監視し *.apk が削除・追加されれば自動処理するクラス

4803     private final class AppDirObserver extends FileObserver {
4804         public AppDirObserver(String path, int mask, boolean isrom) {
4805             super(path, mask);
4806             mRootDir = path;
4807             mIsRom = isrom;
4808         }
4809 
4810         public void onEvent(int event, String path) {
4811             String removedPackage = null;
4812             int removedUid = -1;
4813             String addedPackage = null;
4814             int addedUid = -1;
4815 
4816             // TODO post a message to the handler to obtain serial ordering
4817             synchronized (mInstallLock) {
4818                 String fullPathStr = null;
4819                 File fullPath = null;
4820                 if (path != null) {
4821                     fullPath = new File(mRootDir, path);
4822                     fullPathStr = fullPath.getPath();
4823                 }
4824 
4825                 if (DEBUG_APP_DIR_OBSERVER)
4826                     Log.v(TAG, "File " + fullPathStr + " changed: " + Integer.toHexString(event));
4827 
                     // *.apk 以外は弾く
4828                 if (!isPackageFilename(path)) {
4829                     if (DEBUG_APP_DIR_OBSERVER)
4830                         Log.v(TAG, "Ignoring change of non-package file: " + fullPathStr);
4831                     return;
4832                 }
4833 
                     // 他の経路でインストールされたパッケージは看過
4834                 // Ignore packages that are being installed or
4835                 // have just been installed.
4836                 if (ignoreCodePath(fullPathStr)) {
4837                     return;
4838                 }
4839                 PackageParser.Package p = null;
4840                 // reader
4841                 synchronized (mPackages) {
4842                     p = mAppDirs.get(fullPathStr);
4843                 }

                     // パッケージが削除または移動された場合
4844                 if ((event&REMOVE_EVENTS) != 0) {
4845                     if (p != null) {
4846                         removePackageLI(p, true);
4847                         removedPackage = p.applicationInfo.packageName;
4848                         removedUid = p.applicationInfo.uid;
4849                     }
4850                 }
4851 

                     // パッケージが追加された場合
4852                 if ((event&ADD_EVENTS) != 0) {
4853                     if (p == null) {
4854                         p = scanPackageLI(fullPath,
4855                                 (mIsRom ? PackageParser.PARSE_IS_SYSTEM
4856                                         | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
4857                                 PackageParser.PARSE_CHATTY |
4858                                 PackageParser.PARSE_MUST_BE_APK,
4859                                 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
4860                                 System.currentTimeMillis());
4861                         if (p != null) {
4862                             /*
4863                              * TODO this seems dangerous as the package may have
4864                              * changed since we last acquired the mPackages
4865                              * lock.
4866                              */
4867                             // writer
4868                             synchronized (mPackages) {
4869                                 updatePermissionsLPw(p.packageName, p,
4870                                         p.permissions.size() > 0, false, false);
4871                             }
4872                             addedPackage = p.applicationInfo.packageName;
4873                             addedUid = p.applicationInfo.uid;
4874                         }
4875                     }
4876                 }
4877 
4878                 // reader
4879                 synchronized (mPackages) {
                         // /data/system/packages.xml, packages.list を最新の状態に更新
4880                     mSettings.writeLPr();
4881                 }
4882             }
4883 

                 // アンインストール完了 or インストール完了をブロードキャスト
4884             if (removedPackage != null) {
4885                 Bundle extras = new Bundle(1);
4886                 extras.putInt(Intent.EXTRA_UID, removedUid);
4887                 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
4888                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
4889                         extras, null, null);
4890             }
4891             if (addedPackage != null) {
4892                 Bundle extras = new Bundle(1);
4893                 extras.putInt(Intent.EXTRA_UID, addedUid);
4894                 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
4895                         extras, null, null);
4896             }
4897         }
4898 
4899         private final String mRootDir;
4900         private final boolean mIsRom;
4901     }

PackageManagerService.scanDirLI()

frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より


         // 指定ディレクトリ下の apk 群を走査し無効なものがあれば削除
2753     private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
2754         String[] files = dir.list();
2755         if (files == null) {
2756             Log.d(TAG, "No files in app dir " + dir);
2757             return;
2758         }
2759 
2760         if (DEBUG_PACKAGE_SCANNING) {
2761             Log.d(TAG, "Scanning app dir " + dir);
2762         }
2763 
2764         int i;
2765         for (i=0; i<files.length; i++) {
2766             File file = new File(dir, files[i]);
2767             if (!isPackageFilename(files[i])) {
2768                 // Ignore entries which are not apk's
2769                 continue;
2770             }
                 // apk からパッケージ情報を取得
2771             PackageParser.Package pkg = scanPackageLI(file,
2772                     flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
2773             // Don't mess around with apps in system partition.
2774             if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
2775                     mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
2776                 // Delete the apk
2777                 Slog.w(TAG, "Cleaning up failed install of " + file);
2778                 file.delete();
2779             }
2780         }
2781     }

PackageManagerService.scanPackageLI()

frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より



         // 指定 apk のパッケージ情報を収集・補完の上、アプリケーションディレクトリ有無の
         // チェックを行い適宜修正または新規作成し、パッケージ情報を内部テーブルへ追加
2835     /*
2836      *  Scan a package and return the newly parsed package.
2837      *  Returns null in case of errors and the error code is stored in mLastScanError
2838      */
2839     private PackageParser.Package scanPackageLI(File scanFile,
2840             int parseFlags, int scanMode, long currentTime) {
2841         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2842         String scanPath = scanFile.getPath();
2843         parseFlags |= mDefParseFlags;
2844         PackageParser pp = new PackageParser(scanPath);
2845         pp.setSeparateProcesses(mSeparateProcesses);
2846         pp.setOnlyCoreApps(mOnlyCore);

             // 当該 apk のパッケージ情報取得を試行
2847         final PackageParser.Package pkg = pp.parsePackage(scanFile,
2848                 scanPath, mMetrics, parseFlags);
2849         if (pkg == null) {
2850             mLastScanError = pp.getParseError();
2851             return null;
2852         }
2853         PackageSetting ps = null;
2854         PackageSetting updatedPkg;
2855         // reader
2856         synchronized (mPackages) {
2857             // Look to see if we already know about this package.
2858             String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
2859             if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
2860                 // This package has been renamed to its original name.  Let's
2861                 // use that.
2862                 ps = mSettings.peekPackageLPr(oldName);
2863             }
2864             // If there was no original package, see one for the real package name.
2865             if (ps == null) {
2866                 ps = mSettings.peekPackageLPr(pkg.packageName);
2867             }
2868             // Check to see if this package could be hiding/updating a system
2869             // package.  Must look for it either under the original or real
2870             // package name depending on our state.
2871             updatedPkg = mSettings.mDisabledSysPackages.get(
2872                     ps != null ? ps.name : pkg.packageName);
2873         }
                     :

             // パッケージの証明書の整合性を確認
2915         // Verify certificates against what was last scanned
2916         if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2917             Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2918             return null;
2919         }
2920         // The apk is forward locked (not public) if its code and resources
2921         // are kept in different files.
2922         // TODO grab this value from PackageSettings
2923         if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
2924             parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
2925         }
2927         String codePath = null;
2926 
2928         String resPath = null;
2929         if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
2930             if (ps != null && ps.resourcePathString != null) {
2931                 resPath = ps.resourcePathString;
2932             } else {
2933                 // Should not happen at all. Just log an error.
2934                 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
2935             }
2936         } else {
2937             resPath = pkg.mScanPath;
2938         }
2939         codePath = pkg.mScanPath;
2940         // Set application objects path explicitly.
2941         setApplicationInfoPaths(pkg, codePath, resPath);
2942         // Note that we invoke the following method only if we are about to unpack an application
2943         return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime);
2944     }
                                     :

         // パッケージの証明書の整合性を確認
2808     private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2809             PackageParser.Package pkg, File srcFile, int parseFlags) {
2810         if (GET_CERTIFICATES) {
2811             if (ps != null
2812                     && ps.codePath.equals(srcFile)
2813                     && ps.timeStamp == srcFile.lastModified()) {
2814                 if (ps.signatures.mSignatures != null
2815                         && ps.signatures.mSignatures.length != 0) {
2816                     // Optimization: reuse the existing cached certificates
2817                     // if the package appears to be unchanged.
2818                     pkg.mSignatures = ps.signatures.mSignatures;
2819                     return true;
2820                 }
2821                 
2822                 Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures.  Collecting certs again to recover them.");
2823             } else {
2824                 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2825             }
2826             
2827             if (!pp.collectCertificates(pkg, parseFlags)) {
2828                 mLastScanError = pp.getParseError();
2829                 return false;
2830             }
2831         }
2832         return true;
2833     }
                                     :


3127     private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
3128             int parseFlags, int scanMode, long currentTime) {
3129         File scanFile = new File(pkg.mScanPath);
                              :

3137         mScanningPath = scanFile;
                              :

3190         // Initialize package source and resource directories
3191         File destCodeFile = new File(pkg.applicationInfo.sourceDir);
3192         File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
3193 
3194         SharedUserSetting suid = null;
3195         PackageSetting pkgSetting = null;
3196 
3197         if (!isSystemApp(pkg)) {
3198             // Only system apps can use these features.
3199             pkg.mOriginalPackages = null;
3200             pkg.mRealPackage = null;
3201             pkg.mAdoptPermissions = null;
3202         }
3203 
3204         // writer
3205         synchronized (mPackages) {
                                  :

                 // パッケージに SharedUserId 指定ありならその UID を取得
3245             if (pkg.mSharedUserId != null) {
3246                 suid = mSettings.getSharedUserLPw(pkg.mSharedUserId,
3247                         pkg.applicationInfo.flags, true);
3248                 if (suid == null) {
3249                     Slog.w(TAG, "Creating application package " + pkg.packageName
3250                             + " for shared user failed");
3251                     mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3252                     return null;
3253                 }
3254                 if (DEBUG_PACKAGE_SCANNING) {
3255                     if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3256                         Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
3257                                 + "): packages=" + suid.packages);
3258                 }
3259             }
3260             
3261             // Check if we are renaming from an original package name.
                                  :

                 // Settings クラスの管理する mPackages テーブルの要素である PackageSetting 情報を
                 // 取得 or 存在しなければ新規に生成。パラメータ末尾の false は mPackages テーブルへの
                 // 自動追加を抑止するフラグ

3316             // Just create the setting, don't add it yet. For already existing packages
3317             // the PkgSetting exists already and doesn't have to be created.
3318             pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
3319                     destResourceFile, pkg.applicationInfo.nativeLibraryDir,
3320                     pkg.applicationInfo.flags, true, false);
3321             if (pkgSetting == null) {
3322                 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
3323                 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3324                 return null;
3325             }
                                  :

                 // パッケージの UID をセット
3355             pkg.applicationInfo.uid = pkgSetting.userId;
3356             pkg.mExtras = pkgSetting;
                                  :

3426         }
3427 
3428         final String pkgName = pkg.packageName;
3429         
3430         final long scanFileTime = scanFile.lastModified();
3431         final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
3432         pkg.applicationInfo.processName = fixProcessName(
3433                 pkg.applicationInfo.packageName,
3434                 pkg.applicationInfo.processName,
3435                 pkg.applicationInfo.uid);
3436 
3437         File dataPath;
3438         if (mPlatformPackage == pkg) {
3439             // The system package is special.
3440             dataPath = new File (Environment.getDataDirectory(), "system");
3441             pkg.applicationInfo.dataDir = dataPath.getPath();
3442         } else {
3443             // This is a normal package, need to make its data directory.
3444             dataPath = getDataPathForPackage(pkg.packageName, 0);
3445             
3446             boolean uidError = false;
3447             
                 // アプリケーションのデータディレクトリが既存(≒インストールずみ)の場合
3448             if (dataPath.exists()) {
3449                 mOutPermissions[1] = 0;
3450                 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
3451 
                     // UID が一致しなければアンインストールの上再インストールを試みる
3452                 // If we have mismatched owners for the data path, we have a problem.
3453                 if (mOutPermissions[1] != pkg.applicationInfo.uid) {
3454                     boolean recovered = false;
3455                     if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
3456                         // If this is a system app, we can at least delete its
3457                         // current data so the application will still work.
3458                         int ret = mInstaller.remove(pkgName, 0);
3459                         if (ret >= 0) {
3460                             // TODO: Kill the processes first
3461                             // Remove the data directories for all users
3462                             mUserManager.removePackageForAllUsers(pkgName);
3463                             // Old data gone!
3464                             String msg = "System package " + pkg.packageName
3465                                     + " has changed from uid: "
3466                                     + mOutPermissions[1] + " to "
3467                                     + pkg.applicationInfo.uid + "; old data erased";
3468                             reportSettingsProblem(Log.WARN, msg);
3469                             recovered = true;
3470 
3471                             // And now re-install the app.
3472                             ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
3473                                     pkg.applicationInfo.uid);
3474                             if (ret == -1) {
3475                                 // Ack should not happen!
3476                                 msg = "System package " + pkg.packageName
3477                                         + " could not have data directory re-created after delete.";
3478                                 reportSettingsProblem(Log.WARN, msg);
3479                                 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3480                                 return null;
3481                             }
3482                             // Create data directories for all users
3483                             mUserManager.installPackageForAllUsers(pkgName,
3484                                     pkg.applicationInfo.uid);
3485                         }
3486                         if (!recovered) {
3487                             mHasSystemUidErrors = true;
3488                         }
3489                     }
3490                     if (!recovered) {
3491                         pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
3492                             + pkg.applicationInfo.uid + "/fs_"
3493                             + mOutPermissions[1];
3494                         pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
3495                         String msg = "Package " + pkg.packageName
3496                                 + " has mismatched uid: "
3497                                 + mOutPermissions[1] + " on disk, "
3498                                 + pkg.applicationInfo.uid + " in settings";
3499                         // writer
3500                         synchronized (mPackages) {
3501                             mSettings.mReadMessages.append(msg);
3502                             mSettings.mReadMessages.append('\n');
3503                             uidError = true;
3504                             if (!pkgSetting.uidError) {
3505                                 reportSettingsProblem(Log.ERROR, msg);
3506                             }
3507                         }
3508                     }
3509                 }
3510                 pkg.applicationInfo.dataDir = dataPath.getPath();

                 // データディレクトリが存在しない場合
3511             } else {
3512                 if (DEBUG_PACKAGE_SCANNING) {
3513                     if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3514                         Log.v(TAG, "Want this data dir: " + dataPath);
3515                 }

                     // データディレクトリを作成し当該 UID について所定のパーミッションを付与
3516                 //invoke installer to do the actual installation
3517                 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
3518                         pkg.applicationInfo.uid);
3519                 if (ret < 0) {
3520                     // Error from installer
3521                     mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3522                     return null;
3523                 }
3524                 // Create data directories for all users
3525                 mUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
3526 
3527                 if (dataPath.exists()) {
3528                     pkg.applicationInfo.dataDir = dataPath.getPath();
3529                 } else {
3530                     Slog.w(TAG, "Unable to create data directory: " + dataPath);
3531                     pkg.applicationInfo.dataDir = null;
3532                 }
3533             }
                                  :

3633         // Request the ActivityManager to kill the process(only for existing packages)
3634         // so that we do not end up in a confused state while the user is still using the older
3635         // version of the application while the new one gets installed.
3636         if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
3637             killApplication(pkg.applicationInfo.packageName,
3638                         pkg.applicationInfo.uid);
3639         }
3640 
3641         // writer
3642         synchronized (mPackages) {
3643             // We don't expect installation to fail beyond this point,
3644             if ((scanMode&SCAN_MONITOR) != 0) {
3645                 mAppDirs.put(pkg.mPath, pkg);
3646             }
3647             // Add the new setting to mSettings
3648             mSettings.insertPackageSettingLPw(pkgSetting, pkg);
3649             // Add the new setting to mPackages
3650             mPackages.put(pkg.applicationInfo.packageName, pkg);
                                  :

3672             int N = pkg.providers.size();
3673             StringBuilder r = null;
3674             int i;
3675             for (i=0; i<N; i++) {
3676                 PackageParser.Provider p = pkg.providers.get(i);
3677                 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
3678                         p.info.processName, pkg.applicationInfo.uid);
3679                 mProvidersByComponent.put(new ComponentName(p.info.packageName,
3680                         p.info.name), p);
                                  :

3720                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3721                     if (r == null) {
3722                         r = new StringBuilder(256);
3723                     } else {
3724                         r.append(' ');
3725                     }
3726                     r.append(p.info.name);
3727                 }
3728             }
                                  :
3732 
3733             N = pkg.services.size();
3734             r = null;
3735             for (i=0; i<N; i++) {
3736                 PackageParser.Service s = pkg.services.get(i);
3737                 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
3738                         s.info.processName, pkg.applicationInfo.uid);
3739                 mServices.addService(s);
3740                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3741                     if (r == null) {
3742                         r = new StringBuilder(256);
3743                     } else {
3744                         r.append(' ');
3745                     }
3746                     r.append(s.info.name);
3747                 }
3748             }
                                  :
3752 
3753             N = pkg.receivers.size();
3754             r = null;
3755             for (i=0; i<N; i++) {
3756                 PackageParser.Activity a = pkg.receivers.get(i);
3757                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3758                         a.info.processName, pkg.applicationInfo.uid);
3759                 mReceivers.addActivity(a, "receiver");
3760                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3761                     if (r == null) {
3762                         r = new StringBuilder(256);
3763                     } else {
3764                         r.append(' ');
3765                     }
3766                     r.append(a.info.name);
3767                 }
3768             }
                                  :

3773             N = pkg.activities.size();
3774             r = null;
3775             for (i=0; i<N; i++) {
3776                 PackageParser.Activity a = pkg.activities.get(i);
3777                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3778                         a.info.processName, pkg.applicationInfo.uid);
3779                 mActivities.addActivity(a, "activity");
3780                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3781                     if (r == null) {
3782                         r = new StringBuilder(256);
3783                     } else {
3784                         r.append(' ');
3785                     }
3786                     r.append(a.info.name);
3787                 }
3788             }
                                  :

3793             N = pkg.permissionGroups.size();
3794             r = null;
3795             for (i=0; i<N; i++) {
3796                 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
3797                 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
3798                 if (cur == null) {
3799                     mPermissionGroups.put(pg.info.name, pg);
3800                     if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3801                         if (r == null) {
3802                             r = new StringBuilder(256);
3803                         } else {
3804                             r.append(' ');
3805                         }
3806                         r.append(pg.info.name);
3807                     }
3808                 } else {
3809                     Slog.w(TAG, "Permission group " + pg.info.name + " from package "
3810                             + pg.info.packageName + " ignored: original from "
3811                             + cur.info.packageName);
3812                     if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3813                         if (r == null) {
3814                             r = new StringBuilder(256);
3815                         } else {
3816                             r.append(' ');
3817                         }
3818                         r.append("DUP:");
3819                         r.append(pg.info.name);
3820                     }
3821                 }
3822             }
                                  :

3826 
3827             N = pkg.permissions.size();
3828             r = null;
3829             for (i=0; i<N; i++) {
3830                 PackageParser.Permission p = pkg.permissions.get(i);
3831                 HashMap<String, BasePermission> permissionMap =
3832                         p.tree ? mSettings.mPermissionTrees
3833                         : mSettings.mPermissions;
3834                 p.group = mPermissionGroups.get(p.info.group);
3835                 if (p.info.group == null || p.group != null) {
3836                     BasePermission bp = permissionMap.get(p.info.name);
3837                     if (bp == null) {
3838                         bp = new BasePermission(p.info.name, p.info.packageName,
3839                                 BasePermission.TYPE_NORMAL);
3840                         permissionMap.put(p.info.name, bp);
3841                     }
3842                     if (bp.perm == null) {
3843                         if (bp.sourcePackage == null
3844                                 || bp.sourcePackage.equals(p.info.packageName)) {
3845                             BasePermission tree = findPermissionTreeLP(p.info.name);
3846                             if (tree == null
3847                                     || tree.sourcePackage.equals(p.info.packageName)) {
3848                                 bp.packageSetting = pkgSetting;
3849                                 bp.perm = p;
3850                                 bp.uid = pkg.applicationInfo.uid;
3851                                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3852                                     if (r == null) {
3853                                         r = new StringBuilder(256);
3854                                     } else {
3855                                         r.append(' ');
3856                                     }
3857                                     r.append(p.info.name);
3858                                 }
3859                             } else {
3860                                 Slog.w(TAG, "Permission " + p.info.name + " from package "
3861                                         + p.info.packageName + " ignored: base tree "
3862                                         + tree.name + " is from package "
3863                                         + tree.sourcePackage);
3864                             }
3865                         } else {
3866                             Slog.w(TAG, "Permission " + p.info.name + " from package "
3867                                     + p.info.packageName + " ignored: original from "
3868                                     + bp.sourcePackage);
3869                         }
3870                     } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3871                         if (r == null) {
3872                             r = new StringBuilder(256);
3873                         } else {
3874                             r.append(' ');
3875                         }
3876                         r.append("DUP:");
3877                         r.append(p.info.name);
3878                     }
3879                     if (bp.perm == p) {
3880                         bp.protectionLevel = p.info.protectionLevel;
3881                     }
3882                 } else {
3883                     Slog.w(TAG, "Permission " + p.info.name + " from package "
3884                             + p.info.packageName + " ignored: no group "
3885                             + p.group);
3886                 }
3887             }
3888             if (r != null) {
3889                 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Permissions: " + r);
3890             }
3891 
3892             N = pkg.instrumentation.size();
3893             r = null;
3894             for (i=0; i<N; i++) {
3895                 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3896                 a.info.packageName = pkg.applicationInfo.packageName;
3897                 a.info.sourceDir = pkg.applicationInfo.sourceDir;
3898                 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
3899                 a.info.dataDir = pkg.applicationInfo.dataDir;
3900                 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
3901                 mInstrumentation.put(a.getComponentName(), a);
3902                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3903                     if (r == null) {
3904                         r = new StringBuilder(256);
3905                     } else {
3906                         r.append(' ');
3907                     }
3908                     r.append(a.info.name);
3909                 }
3910             }
3911             if (r != null) {
3912                 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Instrumentation: " + r);
3913             }
3914 
3915             if (pkg.protectedBroadcasts != null) {
3916                 N = pkg.protectedBroadcasts.size();
3917                 for (i=0; i<N; i++) {
3918                     mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
3919                 }
3920             }
3921 
3922             pkgSetting.setTimeStamp(scanFileTime);
3923         }
3924 
3925         return pkg;
3926     }
3927 

Settings.getPackageLPw()

frameworks/base/services/java/com/android/server/pm/Settings.java より



 164     PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
 165             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
 166             String nativeLibraryPathString, int pkgFlags, boolean create, boolean add) {
 167         final String name = pkg.packageName;
 168         PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
 169                 resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags, create, add);
 170         return p;
 171     }
                    :


 324     private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
 325             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
 326             String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) {
 327         PackageSetting p = mPackages.get(name);
 
             // mPackages テーブル上に該当するパッケージ名のエントリが存在
 328         if (p != null) {
 329             if (!p.codePath.equals(codePath)) {
 330                 // Check to see if its a disabled system app
 331                 if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
 332                     // This is an updated system app with versions in both system
 333                     // and data partition. Just let the most recent version
 334                     // take precedence.
 335                     Slog.w(PackageManagerService.TAG, "Trying to update system app code path from " +
 336                             p.codePathString + " to " + codePath.toString());
 337                 } else {
 338                     // Just a change in the code path is not an issue, but
 339                     // let's log a message about it.
 340                     Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from " + p.codePath
 341                             + " to " + codePath + "; Retaining data and using new");
 342                     /*
 343                      * Since we've changed paths, we need to prefer the new
 344                      * native library path over the one stored in the
 345                      * package settings since we might have moved from
 346                      * internal to external storage or vice versa.
 347                      */
 348                     p.nativeLibraryPathString = nativeLibraryPathString;
 349                 }
 350             }
 351             if (p.sharedUser != sharedUser) {
 352                 PackageManagerService.reportSettingsProblem(Log.WARN,
 353                         "Package " + name + " shared user changed from "
 354                         + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
 355                         + " to "
 356                         + (sharedUser != null ? sharedUser.name : "<nothing>")
 357                         + "; replacing with new");
 358                 p = null;
 359             } else {
 360                 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
 361                     // If what we are scanning is a system package, then
 362                     // make it so, regardless of whether it was previously
 363                     // installed only in the data partition.
 364                     p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
 365                 }
 366             }
 367         }

             // パッケージ名のエントリが存在しない
 368         if (p == null) {
 369             // Create a new PackageSettings entry. this can end up here because
 370             // of code path mismatch or user id mismatch of an updated system partition
 371             if (!create) {
 372                 return null;
 373             }
 
                 // PackageSetting 情報を新規作成
 374             if (origPackage != null) {
 375                 // We are consuming the data from an existing package.
 376                 p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
 377                         nativeLibraryPathString, vc, pkgFlags);
 378                 if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package " + name
 379                         + " is adopting original package " + origPackage.name);
 380                 // Note that we will retain the new package's signature so
 381                 // that we can keep its data.
 382                 PackageSignatures s = p.signatures;
 383                 p.copyFrom(origPackage);
 384                 p.signatures = s;
 385                 p.sharedUser = origPackage.sharedUser;
 386                 p.userId = origPackage.userId;
 387                 p.origPackage = origPackage;
 388                 mRenamedPackages.put(name, origPackage.name);
 389                 name = origPackage.name;
 390                 // Update new package state.
 391                 p.setTimeStamp(codePath.lastModified());
 392             } else {
 393                 p = new PackageSetting(name, realName, codePath, resourcePath,
 394                         nativeLibraryPathString, vc, pkgFlags);
 395                 p.setTimeStamp(codePath.lastModified());
 396                 p.sharedUser = sharedUser;
 397                 // If this is not a system app, it starts out stopped.
 398                 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
 399                     if (DEBUG_STOPPED) {
 400                         RuntimeException e = new RuntimeException("here");
 401                         e.fillInStackTrace();
 402                         Slog.i(PackageManagerService.TAG, "Stopping package " + name, e);
 403                     }
 404                     p.stopped = true;
 405                     p.notLaunched = true;
 406                 }
 
                     // SharedUserId が指定されていればその UID を採用
 407                 if (sharedUser != null) {
 408                     p.userId = sharedUser.userId;
 409                 } else if (PackageManagerService.MULTIPLE_APPLICATION_UIDS) {
 410                     // Clone the setting here for disabled system packages
 411                     PackageSetting dis = mDisabledSysPackages.get(name);
 412                     if (dis != null) {
 413                         // For disabled packages a new setting is created
 414                         // from the existing user id. This still has to be
 415                         // added to list of user id's
 416                         // Copy signatures from previous setting
 417                         if (dis.signatures.mSignatures != null) {
 418                             p.signatures.mSignatures = dis.signatures.mSignatures.clone();
 419                         }
 420                         p.userId = dis.userId;
 421                         // Clone permissions
 422                         p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
 423                         // Clone component info
 424                         p.disabledComponents = new HashSet<String>(dis.disabledComponents);
 425                         p.enabledComponents = new HashSet<String>(dis.enabledComponents);
 426                         // Add new setting to list of user ids
 427                         addUserIdLPw(p.userId, p, name);
 428                     } else {
 429                         // Assign new user id
 430                         p.userId = newUserIdLPw(p);
 431                     }
 432                 } else {
 433                     p.userId = PackageManagerService.FIRST_APPLICATION_UID;
 434                 }
 435             }
 436             if (p.userId < 0) {
 437                 PackageManagerService.reportSettingsProblem(Log.WARN,
 438                         "Package " + name + " could not be assigned a valid uid");
 439                 return null;
 440             }
 
                 // add パラメータが true なら新規 PackageSetting 情報を mPackages に追加
 441             if (add) {
 442                 // Finish adding new package by adding it and updating shared
 443                 // user preferences
 444                 addPackageSettingLPw(p, name, sharedUser);
 445             }
 446         }
 447         return p;
 448     }
 

PackageParser.parsePackage()

frameworks/base/core/java/android/content/pm/PackageParser.java より

PackageParser.Package クラス

2927     public final static class Package {
2928         public String packageName;
2929 
2930         // For now we only support one application per package.
2931         public final ApplicationInfo applicationInfo = new ApplicationInfo();
2932 
2933         public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
2934         public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
2935         public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
2936         public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
2937         public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
2938         public final ArrayList<Service> services = new ArrayList<Service>(0);
2939         public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
2940 
2941         public final ArrayList<String> requestedPermissions = new ArrayList<String>();
2942 
2943         public ArrayList<String> protectedBroadcasts;
2944         
2945         public ArrayList<String> usesLibraries = null;
2946         public ArrayList<String> usesOptionalLibraries = null;
2947         public String[] usesLibraryFiles = null;
2948 
2949         public ArrayList<String> mOriginalPackages = null;
2950         public String mRealPackage = null;
2951         public ArrayList<String> mAdoptPermissions = null;
2952         
2953         // We store the application meta-data independently to avoid multiple unwanted references
2954         public Bundle mAppMetaData = null;
2955 
2956         // If this is a 3rd party app, this is the path of the zip file.
2957         public String mPath;
2958 
2959         // The version code declared for this package.
2960         public int mVersionCode;
2961         
2962         // The version name declared for this package.
2963         public String mVersionName;
2964         
2965         // The shared user id that this package wants to use.
2966         public String mSharedUserId;
2967 
2968         // The shared user label that this package wants to use.
2969         public int mSharedUserLabel;
2970 
2971         // Signatures that were read from the package.
2972         public Signature mSignatures[];
2973 
2974         // For use by package manager service for quick lookup of
2975         // preferred up order.
2976         public int mPreferredOrder = 0;
2977 
2978         // For use by the package manager to keep track of the path to the
2979         // file an app came from.
2980         public String mScanPath;
2981         
2982         // For use by package manager to keep track of where it has done dexopt.
2983         public boolean mDidDexOpt;
2984         
2985         // User set enabled state.
2986         public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2987 
2988         // Whether the package has been stopped.
2989         public boolean mSetStopped = false;
2990 
2991         // Additional data supplied by callers.
2992         public Object mExtras;
2993 
2994         // Whether an operation is currently pending on this package
2995         public boolean mOperationPending;
2996 
2997         /*
2998          *  Applications hardware preferences
2999          */
3000         public final ArrayList<ConfigurationInfo> configPreferences =
3001                 new ArrayList<ConfigurationInfo>();
3002 
3003         /*
3004          *  Applications requested features
3005          */
3006         public ArrayList<FeatureInfo> reqFeatures = null;
3007 
3008         public int installLocation;
3009 
3010         /**
3011          * Digest suitable for comparing whether this package's manifest is the
3012          * same as another.
3013          */
3014         public ManifestDigest manifestDigest;
3015 
3016         public Package(String _name) {
3017             packageName = _name;
3018             applicationInfo.packageName = _name;
3019             applicationInfo.uid = -1;
3020         }
                      :
3053     }
                      :


         // apk ファイルの AndroidManifest.xml からパッケージ情報を取得
 390     public  Package parsePackage(File sourceFile, String destCodePath,
 391             DisplayMetrics metrics, int flags) {
 392         mParseError = PackageManager.INSTALL_SUCCEEDED;
 393 
 394         mArchiveSourcePath = sourceFile.getPath();
                        :

 414         XmlResourceParser parser = null;
 415         AssetManager assmgr = null;
 416         Resources res = null;
 417         boolean assetError = true;
 418         try {
 419             assmgr = new AssetManager();
 420             int cookie = assmgr.addAssetPath(mArchiveSourcePath);
 421             if (cookie != 0) {
 422                 res = new Resources(assmgr, metrics, null);
 423                 assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 424                         Build.VERSION.RESOURCES_SDK_INT);
 425                 parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
 426                 assetError = false;
 427             } else {
 428                 Slog.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);
 429             }
 430         } catch (Exception e) {
 431             Slog.w(TAG, "Unable to read AndroidManifest.xml of "
 432                     + mArchiveSourcePath, e);
 433         }
 434         if (assetError) {
 435             if (assmgr != null) assmgr.close();
 436             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
 437             return null;
 438         }
 439         String[] errorText = new String[1];
 440         Package pkg = null;
 441         Exception errorException = null;
 442         try {
                 // AndroidManifest.xml のパースを実行
 443             // XXXX todo: need to figure out correct configuration.
 444             pkg = parsePackage(res, parser, flags, errorText);
 445         } catch (Exception e) {
 446             errorException = e;
 447             mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
 448         }
 449 
 450 
 451         if (pkg == null) {
 452             // If we are only parsing core apps, then a null with INSTALL_SUCCEEDED
 453             // just means to skip this app so don't make a fuss about it.
 454             if (!mOnlyCoreApps || mParseError != PackageManager.INSTALL_SUCCEEDED) {
 455                 if (errorException != null) {
 456                     Slog.w(TAG, mArchiveSourcePath, errorException);
 457                 } else {
 458                     Slog.w(TAG, mArchiveSourcePath + " (at "
 459                             + parser.getPositionDescription()
 460                             + "): " + errorText[0]);
 461                 }
 462                 if (mParseError == PackageManager.INSTALL_SUCCEEDED) {
 463                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
 464                 }
 465             }
 466             parser.close();
 467             assmgr.close();
 468             return null;
 469         }
 470 
 471         parser.close();
 472         assmgr.close();
 473 
 474         // Set code and resource paths
 475         pkg.mPath = destCodePath;
 476         pkg.mScanPath = mArchiveSourcePath;
 477         //pkg.applicationInfo.sourceDir = destCodePath;
 478         //pkg.applicationInfo.publicSourceDir = destRes;
 479         pkg.mSignatures = null;
 480 
 481         return pkg;
 482     }
 483 
                  :

         //  AndroidManifest.xml をパースしてパッケージ情報を返す
 812     private Package parsePackage(
 813         Resources res, XmlResourceParser parser, int flags, String[] outError)
 814         throws XmlPullParserException, IOException {
 815         AttributeSet attrs = parser;
 816 
 817         mParseInstrumentationArgs = null;
 818         mParseActivityArgs = null;
 819         mParseServiceArgs = null;
 820         mParseProviderArgs = null;
 821         
 822         String pkgName = parsePackageName(parser, attrs, flags, outError);
 823         if (pkgName == null) {
 824             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
 825             return null;
 826         }
 827         int type;
 828 
 829         if (mOnlyCoreApps) {
 830             boolean core = attrs.getAttributeBooleanValue(null, "coreApp", false);
 831             if (!core) {
 832                 mParseError = PackageManager.INSTALL_SUCCEEDED;
 833                 return null;
 834             }
 835         }
 836 
 837         final Package pkg = new Package(pkgName);
 838         boolean foundApp = false;
 839         
 840         TypedArray sa = res.obtainAttributes(attrs,
 841                 com.android.internal.R.styleable.AndroidManifest);
 842         pkg.mVersionCode = sa.getInteger(
 843                 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
 844         pkg.mVersionName = sa.getNonConfigurationString(
 845                 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
 846         if (pkg.mVersionName != null) {
 847             pkg.mVersionName = pkg.mVersionName.intern();
 848         }
 849         String str = sa.getNonConfigurationString(
 850                 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
 851         if (str != null && str.length() > 0) {
 852             String nameError = validateName(str, true);
 853             if (nameError != null && !"android".equals(pkgName)) {
 854                 outError[0] = "<manifest> specifies bad sharedUserId name \""
 855                     + str + "\": " + nameError;
 856                 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
 857                 return null;
 858             }
 859             pkg.mSharedUserId = str.intern();
 860             pkg.mSharedUserLabel = sa.getResourceId(
 861                     com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
 862         }
 863         sa.recycle();
 864 
 865         pkg.installLocation = sa.getInteger(
 866                 com.android.internal.R.styleable.AndroidManifest_installLocation,
 867                 PARSE_DEFAULT_INSTALL_LOCATION);
 868         pkg.applicationInfo.installLocation = pkg.installLocation;
 869         
 870         // Resource boolean are -1, so 1 means we don't know the value.
 871         int supportsSmallScreens = 1;
 872         int supportsNormalScreens = 1;
 873         int supportsLargeScreens = 1;
 874         int supportsXLargeScreens = 1;
 875         int resizeable = 1;
 876         int anyDensity = 1;
 877         
 878         int outerDepth = parser.getDepth();
 879         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
 880                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
 881             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
 882                 continue;
 883             }
 884 
 885             String tagName = parser.getName();
 886             if (tagName.equals("application")) {
                             :

 899                 foundApp = true;
 900                 if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
 901                     return null;
 902                 }
 903             } else if (tagName.equals("permission-group")) {
 904                 if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) {
 905                     return null;
 906                 }
 907             } else if (tagName.equals("permission")) {
 908                 if (parsePermission(pkg, res, parser, attrs, outError) == null) {
 909                     return null;
 910                 }
 911             } else if (tagName.equals("permission-tree")) {
 912                 if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
 913                     return null;
 914                 }
 915             } else if (tagName.equals("uses-permission")) {
                             :

 926                 if (name != null && !pkg.requestedPermissions.contains(name)) {
 927                     pkg.requestedPermissions.add(name.intern());
 928                 }
 929 
 930                 XmlUtils.skipCurrentTag(parser);
 931 
 932             } else if (tagName.equals("uses-configuration")) {
                             :

 956                 pkg.configPreferences.add(cPref);
 957 
 958                 XmlUtils.skipCurrentTag(parser);
 959 
 960             } else if (tagName.equals("uses-feature")) {
                             :

 982                 pkg.reqFeatures.add(fi);
                             :

 990                 XmlUtils.skipCurrentTag(parser);
 991 
 992             } else if (tagName.equals("uses-sdk")) {
 993                 if (SDK_VERSION > 0) {
                             :

1045                     if (targetCode != null) {
                             :

1057                         // If the code matches, it definitely targets this SDK.
1058                         pkg.applicationInfo.targetSdkVersion
1059                                 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
1060                     } else {
1061                         pkg.applicationInfo.targetSdkVersion = targetVers;
1062                     }
1063                 }
1064 
1065                 XmlUtils.skipCurrentTag(parser);
1066 
1067             } else if (tagName.equals("supports-screens")) {
1068                 sa = res.obtainAttributes(attrs,
1069                         com.android.internal.R.styleable.AndroidManifestSupportsScreens);
1070 
1071                 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
1072                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
1073                         0);
1074                 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
1075                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
1076                         0);
1077                 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
1078                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
1079                         0);
                             :

1104                 XmlUtils.skipCurrentTag(parser);
1105                 
1106             } else if (tagName.equals("protected-broadcast")) {
                             :

1126                 XmlUtils.skipCurrentTag(parser);
1127                 
1128             } else if (tagName.equals("instrumentation")) {
1129                 if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
1130                     return null;
1131                 }
1132                 
1133             } else if (tagName.equals("original-package")) {
1134                 sa = res.obtainAttributes(attrs,
1135                         com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1136 
1137                 String orig =sa.getNonConfigurationString(
1138                         com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
1139                 if (!pkg.packageName.equals(orig)) {
1140                     if (pkg.mOriginalPackages == null) {
1141                         pkg.mOriginalPackages = new ArrayList<String>();
1142                         pkg.mRealPackage = pkg.packageName;
1143                     }
1144                     pkg.mOriginalPackages.add(orig);
1145                 }
1146 
1147                 sa.recycle();
1148 
1149                 XmlUtils.skipCurrentTag(parser);
1150                 
1151             } else if (tagName.equals("adopt-permissions")) {
1152                 sa = res.obtainAttributes(attrs,
1153                         com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1154 
1155                 String name = sa.getNonConfigurationString(
1156                         com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
1157 
1158                 sa.recycle();
1159 
1160                 if (name != null) {
1161                     if (pkg.mAdoptPermissions == null) {
1162                         pkg.mAdoptPermissions = new ArrayList<String>();
1163                     }
1164                     pkg.mAdoptPermissions.add(name);
1165                 }
1166 
1167                 XmlUtils.skipCurrentTag(parser);
1168                 
1169             } else if (tagName.equals("uses-gl-texture")) {
1170                 // Just skip this tag
1171                 XmlUtils.skipCurrentTag(parser);
1172                 continue;
1173                 
1174             } else if (tagName.equals("compatible-screens")) {
1175                 // Just skip this tag
1176                 XmlUtils.skipCurrentTag(parser);
1177                 continue;
1178                 
1179             } else if (tagName.equals("eat-comment")) {
1180                 // Just skip this tag
1181                 XmlUtils.skipCurrentTag(parser);
1182                 continue;
1183                 
1184             } else if (RIGID_PARSER) {
1185                 outError[0] = "Bad element under <manifest>: "
1186                     + parser.getName();
1187                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1188                 return null;
1189 
1190             } else {
1191                 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1192                         + " at " + mArchiveSourcePath + " "
1193                         + parser.getPositionDescription());
1194                 XmlUtils.skipCurrentTag(parser);
1195                 continue;
1196             }
1197         }
1198 
1199         if (!foundApp && pkg.instrumentation.size() == 0) {
1200             outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
1201             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1202         }
1203 
1204         final int NP = PackageParser.NEW_PERMISSIONS.length;
1205         StringBuilder implicitPerms = null;
1206         for (int ip=0; ip<NP; ip++) {
1207             final PackageParser.NewPermissionInfo npi
1208                     = PackageParser.NEW_PERMISSIONS[ip];
1209             if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
1210                 break;
1211             }
1212             if (!pkg.requestedPermissions.contains(npi.name)) {
1213                 if (implicitPerms == null) {
1214                     implicitPerms = new StringBuilder(128);
1215                     implicitPerms.append(pkg.packageName);
1216                     implicitPerms.append(": compat added ");
1217                 } else {
1218                     implicitPerms.append(' ');
1219                 }
1220                 implicitPerms.append(npi.name);
1221                 pkg.requestedPermissions.add(npi.name);
1222             }
1223         }
1224         if (implicitPerms != null) {
1225             Slog.i(TAG, implicitPerms.toString());
1226         }
1227         
1228         if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
1229                 && pkg.applicationInfo.targetSdkVersion
1230                         >= android.os.Build.VERSION_CODES.DONUT)) {
1231             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
1232         }
1233         if (supportsNormalScreens != 0) {
1234             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
1235         }
1236         if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
1237                 && pkg.applicationInfo.targetSdkVersion
1238                         >= android.os.Build.VERSION_CODES.DONUT)) {
1239             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
1240         }
1241         if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
1242                 && pkg.applicationInfo.targetSdkVersion
1243                         >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
1244             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
1245         }
1246         if (resizeable < 0 || (resizeable > 0
1247                 && pkg.applicationInfo.targetSdkVersion
1248                         >= android.os.Build.VERSION_CODES.DONUT)) {
1249             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
1250         }
1251         if (anyDensity < 0 || (anyDensity > 0
1252                 && pkg.applicationInfo.targetSdkVersion
1253                         >= android.os.Build.VERSION_CODES.DONUT)) {
1254             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
1255         }
1256 
1257         return pkg;
1258     }
                                :


 484     public boolean collectCertificates(Package pkg, int flags) {
 485         pkg.mSignatures = null;
 486 
 487         WeakReference<byte[]> readBufferRef;
 488         byte[] readBuffer = null;
 489         synchronized (mSync) {
 490             readBufferRef = mReadBuffer;
 491             if (readBufferRef != null) {
 492                 mReadBuffer = null;
 493                 readBuffer = readBufferRef.get();
 494             }
 495             if (readBuffer == null) {
 496                 readBuffer = new byte[8192];
 497                 readBufferRef = new WeakReference<byte[]>(readBuffer);
 498             }
 499         }
 500 
 501         try {
 502             JarFile jarFile = new JarFile(mArchiveSourcePath);
 503 
 504             Certificate[] certs = null;
 505 
 506             if ((flags&PARSE_IS_SYSTEM) != 0) {
 507                 // If this package comes from the system image, then we
 508                 // can trust it...  we'll just use the AndroidManifest.xml
 509                 // to retrieve its signatures, not validating all of the
 510                 // files.
 511                 JarEntry jarEntry = jarFile.getJarEntry(ANDROID_MANIFEST_FILENAME);
 512                 certs = loadCertificates(jarFile, jarEntry, readBuffer);
 513                 if (certs == null) {
 514                     Slog.e(TAG, "Package " + pkg.packageName
 515                             + " has no certificates at entry "
 516                             + jarEntry.getName() + "; ignoring!");
 517                     jarFile.close();
 518                     mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
 519                     return false;
 520                 }
 521                 if (DEBUG_JAR) {
 522                     Slog.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry
 523                             + " certs=" + (certs != null ? certs.length : 0));
 524                     if (certs != null) {
 525                         final int N = certs.length;
 526                         for (int i=0; i<N; i++) {
 527                             Slog.i(TAG, "  Public key: "
 528                                     + certs[i].getPublicKey().getEncoded()
 529                                     + " " + certs[i].getPublicKey());
 530                         }
 531                     }
 532                 }
 533             } else {
 534                 Enumeration<JarEntry> entries = jarFile.entries();

                     // "META-INF/MANIFEST.MF" をロード
 535                 final Manifest manifest = jarFile.getManifest();
 536                 while (entries.hasMoreElements()) {
 537                     final JarEntry je = entries.nextElement();
 538                     if (je.isDirectory()) continue;
 539 
 540                     final String name = je.getName();
 541 
 542                     if (name.startsWith("META-INF/"))
 543                         continue;
 544 
                         // MANIFEST.MF より AndroidManifest.xml の SHA1-Digest を取得
 545                     if (ANDROID_MANIFEST_FILENAME.equals(name)) {
 546                         final Attributes attributes = manifest.getAttributes(name);
 547                         pkg.manifestDigest = ManifestDigest.fromAttributes(attributes);
 548                     }
 549 
 550                     final Certificate[] localCerts = loadCertificates(jarFile, je, readBuffer);
 551                     if (DEBUG_JAR) {
 552                         Slog.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName()
 553                                 + ": certs=" + certs + " ("
 554                                 + (certs != null ? certs.length : 0) + ")");
 555                     }
 556 
 557                     if (localCerts == null) {
 558                         Slog.e(TAG, "Package " + pkg.packageName
 559                                 + " has no certificates at entry "
 560                                 + je.getName() + "; ignoring!");
 561                         jarFile.close();
 562                         mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
 563                         return false;
 564                     } else if (certs == null) {
 565                         certs = localCerts;
 566                     } else {
 567                         // Ensure all certificates match.
 568                         for (int i=0; i<certs.length; i++) {
 569                             boolean found = false;
 570                             for (int j=0; j<localCerts.length; j++) {
 571                                 if (certs[i] != null &&
 572                                         certs[i].equals(localCerts[j])) {
 573                                     found = true;
 574                                     break;
 575                                 }
 576                             }
 577                             if (!found || certs.length != localCerts.length) {
 578                                 Slog.e(TAG, "Package " + pkg.packageName
 579                                         + " has mismatched certificates at entry "
 580                                         + je.getName() + "; ignoring!");
 581                                 jarFile.close();
 582                                 mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
 583                                 return false;
 584                             }
 585                         }
 586                     }
 587                 }
 588             }
 589             jarFile.close();
 590 
 591             synchronized (mSync) {
 592                 mReadBuffer = readBufferRef;
 593             }
 594 
 595             if (certs != null && certs.length > 0) {
 596                 final int N = certs.length;
 597                 pkg.mSignatures = new Signature[certs.length];
 598                 for (int i=0; i<N; i++) {
 599                     pkg.mSignatures[i] = new Signature(
 600                             certs[i].getEncoded());
 601                 }
 602             } else {
 603                 Slog.e(TAG, "Package " + pkg.packageName
 604                         + " has no certificates; ignoring!");
 605                 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
 606                 return false;
 607             }
 608         } catch (CertificateEncodingException e) {
 609             Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
 610             mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
 611             return false;
 612         } catch (IOException e) {
 613             Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
 614             mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
 615             return false;
 616         } catch (RuntimeException e) {
 617             Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
 618             mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
 619             return false;
 620         }
 621 
 622         return true;
 623     }
                      :


 357     private Certificate[] loadCertificates(JarFile jarFile, JarEntry je,
 358             byte[] readBuffer) {
 359         try {
 360             // We must read the stream for the JarEntry to retrieve
 361             // its certificates.
 362             InputStream is = new BufferedInputStream(jarFile.getInputStream(je));
 363             while (is.read(readBuffer, 0, readBuffer.length) != -1) {
 364                 // not using
 365             }
 366             is.close();
 367             return je != null ? je.getCertificates() : null;
 368         } catch (IOException e) {
 369             Slog.w(TAG, "Exception reading " + je.getName() + " in "
 370                     + jarFile.getName(), e);
 371         } catch (RuntimeException e) {
 372             Slog.w(TAG, "Exception reading " + je.getName() + " in "
 373                     + jarFile.getName(), e);
 374         }
 375         return null;
 376     }

Installer クラス

frameworks/base/services/java/com/android/server/pm/Installer.java より

  17 package com.android.server.pm;
           :

     // /dev/socket/installd へ要求を送出するクラス
  28 class Installer {
  29     private static final String TAG = "Installer";
  30 
  31     private static final boolean LOCAL_DEBUG = false;
  32 
  33     InputStream mIn;
  34 
  35     OutputStream mOut;
  36 
  37     LocalSocket mSocket;
  38 
  39     byte buf[] = new byte[1024];
  40 
  41     int buflen = 0;
  42 
         // /dev/socket/installd との接続
  43     private boolean connect() {
  44         if (mSocket != null) {
  45             return true;
  46         }
  47         Slog.i(TAG, "connecting...");
  48         try {
  49             mSocket = new LocalSocket();
  50 
  51             LocalSocketAddress address = new LocalSocketAddress("installd",
  52                     LocalSocketAddress.Namespace.RESERVED);
  53 
  54             mSocket.connect(address);
  55 
  56             mIn = mSocket.getInputStream();
  57             mOut = mSocket.getOutputStream();
  58         } catch (IOException ex) {
  59             disconnect();
  60             return false;
  61         }
  62         return true;
  63     }
           :

         // /dev/socket/installd への書き込み
 130     private boolean writeCommand(String _cmd) {
 131         byte[] cmd = _cmd.getBytes();
 132         int len = cmd.length;
 133         if ((len < 1) || (len > 1024))
 134             return false;
 135         buf[0] = (byte) (len & 0xff);
 136         buf[1] = (byte) ((len >> 8) & 0xff);
 137         try {
 138             mOut.write(buf, 0, 2);
 139             mOut.write(cmd, 0, len);
 140         } catch (IOException ex) {
 141             Slog.e(TAG, "write error");
 142             disconnect();
 143             return false;
 144         }
 145         return true;
 146     }
 147 
         // 送受信
 148     private synchronized String transaction(String cmd) {
 149         if (!connect()) {
 150             Slog.e(TAG, "connection failed");
 151             return "-1";
 152         }
 153 
 154         if (!writeCommand(cmd)) {
 155             /*
 156              * If installd died and restarted in the background (unlikely but
 157              * possible) we'll fail on the next write (this one). Try to
 158              * reconnect and write the command one more time before giving up.
 159              */
 160             Slog.e(TAG, "write command failed? reconnect!");
 161             if (!connect() || !writeCommand(cmd)) {
 162                 return "-1";
 163             }
 164         }
 165         if (LOCAL_DEBUG) {
 166             Slog.i(TAG, "send: '" + cmd + "'");
 167         }
 168         if (readReply()) {
 169             String s = new String(buf, 0, buflen);
 170             if (LOCAL_DEBUG) {
 171                 Slog.i(TAG, "recv: '" + s + "'");
 172             }
 173             return s;
 174         } else {
 175             if (LOCAL_DEBUG) {
 176                 Slog.i(TAG, "fail");
 177             }
 178             return "-1";
 179         }
 180     }
 181 
         // コマンドの実行
 182     private int execute(String cmd) {
 183         String res = transaction(cmd);
 184         try {
 185             return Integer.parseInt(res);
 186         } catch (NumberFormatException ex) {
 187             return -1;
 188         }
 189     }
 190 
 191     public int install(String name, int uid, int gid) {
 192         StringBuilder builder = new StringBuilder("install");
 193         builder.append(' ');
 194         builder.append(name);
 195         builder.append(' ');
 196         builder.append(uid);
 197         builder.append(' ');
 198         builder.append(gid);
 199         return execute(builder.toString());
 200     }
 201 
 202     public int dexopt(String apkPath, int uid, boolean isPublic) {
 203         StringBuilder builder = new StringBuilder("dexopt");
 204         builder.append(' ');
 205         builder.append(apkPath);
 206         builder.append(' ');
 207         builder.append(uid);
 208         builder.append(isPublic ? " 1" : " 0");
 209         return execute(builder.toString());
 210     }
 211 
 212     public int movedex(String srcPath, String dstPath) {
 213         StringBuilder builder = new StringBuilder("movedex");
 214         builder.append(' ');
 215         builder.append(srcPath);
 216         builder.append(' ');
 217         builder.append(dstPath);
 218         return execute(builder.toString());
 219     }
                    :

 228     public int remove(String name, int userId) {
 229         StringBuilder builder = new StringBuilder("remove");
 230         builder.append(' ');
 231         builder.append(name);
 232         builder.append(' ');
 233         builder.append(userId);
 234         return execute(builder.toString());
 235     }
                     :

PackageInstaller から InstallAppProgress へインストール要求の引き渡し

packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java より

パッケージインストーラ

  17 package com.android.packageinstaller;
                    :

  42 /*
  43  * This activity is launched when a new application is installed via side loading
  44  * The package is first parsed and the user is notified of parse errors via a dialog.
  45  * If the package is successfully parsed, the user is notified to turn on the install unknown
  46  * applications setting. A memory check is made at this point and the user is notified of out
  47  * of memory conditions if any. If the package is already existing on the device, 
  48  * a confirmation dialog (to replace the existing package) is presented to the user.
  49  * Based on the user response the package is then installed by launching InstallAppConfirm
  50  * sub activity. All state transitions are handled in this activity
  51  */
  52 public class PackageInstallerActivity extends Activity implements OnCancelListener, OnClickListener {
  53     private static final String TAG = "PackageInstaller";
  54     private Uri mPackageURI;    
  55     private boolean localLOGV = false;
  56     PackageManager mPm;
  57     private PackageParser.Package mPkgInfo;
                    :

 235     @Override
 236     protected void onCreate(Bundle icicle) {
 237         super.onCreate(icicle);
 238         //get intent information
 239         final Intent intent = getIntent();
 240         mPackageURI = intent.getData();
 241         mPm = getPackageManager();

             // 対象パッケージの情報を得る
 242         mPkgInfo = PackageUtil.getPackageInfo(mPackageURI);
 243         
 244         // Check for parse errors
 245         if(mPkgInfo == null) {
 246             Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation");
 247             showDialogInner(DLG_PACKAGE_ERROR);
 248             return;
 249         }
 250         
 251         //set view
 252         requestWindowFeature(Window.FEATURE_NO_TITLE);
 253         setContentView(R.layout.install_start);
 254         mInstallConfirm = findViewById(R.id.install_confirm_panel);
 255         mInstallConfirm.setVisibility(View.INVISIBLE);
 256         PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this,
 257                 mPkgInfo.applicationInfo, mPackageURI);
 258         PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);

             // 身元不明アプリのインストールが非許可の設定の場合
 259        //check setting
 260         if(!isInstallingUnknownAppsAllowed()) {
 261             //ask user to enable setting first
 262             showDialogInner(DLG_UNKNOWN_APPS);
 263             return;
 264         }
 265         initiateInstall();
 266     }
 267     
 268     // Generic handling when pressing back key
 269     public void onCancel(DialogInterface dialog) {
 270         finish();
 271     }
 272 
 273     public void onClick(View v) {

             // 「インストール」ボタン押下で InstallAppProgress を呼び出す
 274         if(v == mOk) {
 275             // Start subactivity to actually install the application
 276             Intent newIntent = new Intent();
 277             newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
 278                     mPkgInfo.applicationInfo);
 279             newIntent.setData(mPackageURI);
 280             newIntent.setClass(this, InstallAppProgress.class);
 281             String installerPackageName = getIntent().getStringExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME);
 282             if (installerPackageName != null) {
 283                 newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);
 284             }
 285             if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
                 // InstallAppProgress アクティビティを呼ぶ
 286             startActivity(newIntent);
 287             finish();
 288         } else if(v == mCancel) {
 289             // Cancel and finish
 290             finish();
 291         }
 292     }
 293 }
packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java より
PackageUtil クラス

  17 package com.android.packageinstaller;
                   :

  42 /**
  43  * This is a utility class for defining some utility methods and constants
  44  * used in the package installer application.
  45  */
  46 public class PackageUtil {
  47     public static final String PREFIX="com.android.packageinstaller.";
  48     public static final String INTENT_ATTR_INSTALL_STATUS = PREFIX+"installStatus";
  49     public static final String INTENT_ATTR_APPLICATION_INFO=PREFIX+"applicationInfo";
  50     public static final String INTENT_ATTR_PERMISSIONS_LIST=PREFIX+"PermissionsList";
  51     //intent attribute strings related to uninstall
  52     public static final String INTENT_ATTR_PACKAGE_NAME=PREFIX+"PackageName";
  53     
  54     /*
  55      * Utility method to get application information for a given packageURI
  56      */
  57     public static  ApplicationInfo getApplicationInfo(Uri packageURI) {
  58         final String archiveFilePath = packageURI.getPath();
  59         PackageParser packageParser = new PackageParser(archiveFilePath);
  60         File sourceFile = new File(archiveFilePath);
  61         DisplayMetrics metrics = new DisplayMetrics();
  62         metrics.setToDefaults();
  63         PackageParser.Package pkg = packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
  64         if (pkg == null) {
  65             return null;
  66         }
  67         return pkg.applicationInfo;
  68     }
  69     
  70     /*
  71      * Utility method to get package information for a given packageURI
  72      */
  73     public static  PackageParser.Package getPackageInfo(Uri packageURI) {
  74         final String archiveFilePath = packageURI.getPath();
  75         PackageParser packageParser = new PackageParser(archiveFilePath);
  76         File sourceFile = new File(archiveFilePath);
  77         DisplayMetrics metrics = new DisplayMetrics();
  78         metrics.setToDefaults();

             // 当該パッケージのパッケージ情報を得る
  79         PackageParser.Package pkg =  packageParser.parsePackage(sourceFile,
  80                 archiveFilePath, metrics, 0);
  81         // Nuke the parser reference.
  82         packageParser = null;
  83         return pkg;
  84     }
                     :

InstallAppProgress からシステムへインストール要求〜インストール実処理

packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallAppProgress.java より

  17 package com.android.packageinstaller;
                   :

  46 /**
  47  * This activity corresponds to a download progress screen that is displayed 
  48  * when the user tries
  49  * to install an application bundled as an apk file. The result of the application install
  50  * is indicated in the result code that gets set to the corresponding installation status
  51  * codes defined in PackageManager. If the package being installed already exists,
  52  * the existing package is replaced with the new one.
  53  */
  54 public class InstallAppProgress extends Activity implements View.OnClickListener, OnCancelListener {
  55     private final String TAG="InstallAppProgress";
  56     private boolean localLOGV = false;
  57     private ApplicationInfo mAppInfo;
  58     private Uri mPackageURI;
                   :
         // メッセージハンドラ
  70     private Handler mHandler = new Handler() {
  71         public void handleMessage(Message msg) {
  72             switch (msg.what) {
  73                 case INSTALL_COMPLETE:
  74                     if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
  75                         Intent result = new Intent();
  76                         result.putExtra(Intent.EXTRA_INSTALL_RESULT, msg.arg1);
  77                         setResult(msg.arg1 == PackageManager.INSTALL_SUCCEEDED
  78                                 ? Activity.RESULT_OK : Activity.RESULT_FIRST_USER,
  79                                         result);
  80                         finish();
  81                         return;
  82                     }
                   :

 158     @Override
 159     public void onCreate(Bundle icicle) {
 160         super.onCreate(icicle);
 161         Intent intent = getIntent();
 162         mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
 163         mPackageURI = intent.getData();
 164         initView();
 165     }
                    :
        // インストール処理完了時に通知を受けるためのオブザーバクラス
 200     class PackageInstallObserver extends IPackageInstallObserver.Stub {
 201         public void packageInstalled(String packageName, int returnCode) {
 202             Message msg = mHandler.obtainMessage(INSTALL_COMPLETE);
 203             msg.arg1 = returnCode;
 204             mHandler.sendMessage(msg);
 205         }
 206     }
 207 
 208     public void initView() {
 209         setContentView(R.layout.op_progress);
 210         int installFlags = 0;
 211         PackageManager pm = getPackageManager();
 212         try {
                 // 当該パッケージがすでにインストールずみか確認
 213             PackageInfo pi = pm.getPackageInfo(mAppInfo.packageName, 
 214                     PackageManager.GET_UNINSTALLED_PACKAGES);
 215             if(pi != null) {
 216                 installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
 217             }
 218         } catch (NameNotFoundException e) {
 219         }
 220         if((installFlags & PackageManager.INSTALL_REPLACE_EXISTING )!= 0) {
 221             Log.w(TAG, "Replacing package:" + mAppInfo.packageName);
 222         }
 223         PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, mAppInfo,
 224                 mPackageURI);
 225         mLabel = as.label;
 226         PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);
 227         mStatusTextView = (TextView)findViewById(R.id.center_text);
 228         mStatusTextView.setText(R.string.installing);
 229         mExplanationTextView = (TextView) findViewById(R.id.center_explanation);
 230         mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
 231         mProgressBar.setIndeterminate(true);
 232         // Hide button till progress is being displayed
 233         mOkPanel = (View)findViewById(R.id.buttons_panel);
 234         mDoneButton = (Button)findViewById(R.id.done_button);
 235         mLaunchButton = (Button)findViewById(R.id.launch_button);
 236         mOkPanel.setVisibility(View.INVISIBLE);
 237 
 238         String installerPackageName = getIntent().getStringExtra(
 239                 Intent.EXTRA_INSTALLER_PACKAGE_NAME);

             // オブザーバクラスのインスタンスを生成
 240         PackageInstallObserver observer = new PackageInstallObserver();

             // PackageManager にインストール処理を委託
 241         pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);
 242     }
frameworks/base/core/java/android/content/pm/PackageManager.java より
  17 package android.content.pm;
                   :

  37 /**
  38  * Class for retrieving various kinds of information related to the application
  39  * packages that are currently installed on the device.
  40  *
  41  * You can find this class through {@link Context#getPackageManager}.
  42  */
  43 public abstract class PackageManager {
                   :

2137     /**
2138      * @hide
2139      *
2140      * Install a package. Since this may take a little while, the result will
2141      * be posted back to the given observer.  An installation will fail if the calling context
2142      * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the
2143      * package named in the package file's manifest is already installed, or if there's no space
2144      * available on the device.
2145      *
2146      * @param packageURI The location of the package file to install.  This can be a 'file:' or a
2147      * 'content:' URI.
2148      * @param observer An observer callback to get notified when the package installation is
2149      * complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be
2150      * called when that happens.  observer may be null to indicate that no callback is desired.
2151      * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
2152      * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
2153      * @param installerPackageName Optional package name of the application that is performing the
2154      * installation. This identifies which market the package came from.
2155      */
2156     public abstract void installPackage(
2157             Uri packageURI, IPackageInstallObserver observer, int flags,
2158             String installerPackageName);
                   :
frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より

                   :
4903     /* Called when a downloaded package installation has been confirmed by the user */
4904     public void installPackage(
4905             final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
4906         installPackage(packageURI, observer, flags, null);
4907     }
4908 
4909     /* Called when a downloaded package installation has been confirmed by the user */
4910     public void installPackage(
4911             final Uri packageURI, final IPackageInstallObserver observer, final int flags,
4912             final String installerPackageName) {
4913         installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
4914                 null);
4915     }
4916 
4917     @Override
4918     public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
4919             int flags, String installerPackageName, Uri verificationURI,
4920             ManifestDigest manifestDigest) {
4921         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
4922 
             // 呼び元プロセスの UID を取得
4923         final int uid = Binder.getCallingUid();
4924 
4925         final int filteredFlags;
4926 
             // UID が SHELL_UID なら adb 経由でのインストールとみなす
4927         if (uid == Process.SHELL_UID || uid == 0) {
4928             if (DEBUG_INSTALL) {
4929                 Slog.v(TAG, "Install from ADB");
4930             }
4931             filteredFlags = flags | PackageManager.INSTALL_FROM_ADB;
4932         } else {
4933             filteredFlags = flags & ~PackageManager.INSTALL_FROM_ADB;
4934         }
4935 
4936         final Message msg = mHandler.obtainMessage(INIT_COPY);
4937         msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
4938                 verificationURI, manifestDigest);
4939         mHandler.sendMessage(msg);
4940     }
                   :
frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より

                   :
 439     class PackageHandler extends Handler {
 440         private boolean mBound = false;
 441         final ArrayList<HandlerParams> mPendingInstalls =
 442             new ArrayList<HandlerParams>();
 443 
             // DefaultContainerService への接続
 444         private boolean connectToService() {
 445             if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
 446                     " DefaultContainerService");
 447             Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
 448             Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
 449             if (mContext.bindService(service, mDefContainerConn,
 450                     Context.BIND_AUTO_CREATE)) {
 451                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
 452                 mBound = true;
 453                 return true;
 454             }
 455             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
 456             return false;
 457         }
 458 
             // DefaultContainerService からの切断
 459         private void disconnectService() {
 460             mContainerService = null;
 461             mBound = false;
 462             Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
 463             mContext.unbindService(mDefContainerConn);
 464             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
 465         }
                    :
 
 479         void doHandleMessage(Message msg) {
 480             switch (msg.what) {
 481                 case INIT_COPY: {
 482                     if (DEBUG_INSTALL) Slog.i(TAG, "init_copy");
 483                     HandlerParams params = (HandlerParams) msg.obj;
 484                     int idx = mPendingInstalls.size();
 485                     if (DEBUG_INSTALL) Slog.i(TAG, "idx=" + idx);

                         // DefaultContainerService へ未接続なら接続を確立する
 486                     // If a bind was already initiated we dont really
 487                     // need to do anything. The pending install
 488                     // will be processed later on.
 489                     if (!mBound) {
 490                         // If this is the only one pending we might
 491                         // have to bind to the service again.
 492                         if (!connectToService()) {
 493                             Slog.e(TAG, "Failed to bind to media container service");
 494                             params.serviceError();
 495                             return;
 496                         } else {

                                 // 接続成功なら今回のインストール要求をキューへ追加
                                 //  〜接続ハンドラが MCS_BOUND メッセージを自動送出し
                                 //   キュー先頭分のインストールが開始される
 497                             // Once we bind to the service, the first
 498                             // pending request will be processed.
 499                             mPendingInstalls.add(idx, params);
 500                         }

                         // すでに接続ずみの状況
 501                     } else {
 502                         mPendingInstalls.add(idx, params);
 503                         // Already bound to the service. Just make
 504                         // sure we trigger off processing the first request.
 505                         if (idx == 0) {
 506                             mHandler.sendEmptyMessage(MCS_BOUND);
 507                         }
 508                     }
 509                     break;
 510                 }
 511                 case MCS_BOUND: {
 512                     if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
 513                     if (msg.obj != null) {
 514                         mContainerService = (IMediaContainerService) msg.obj;
 515                     }
 516                     if (mContainerService == null) {
 517                         // Something seriously wrong. Bail out
 518                         Slog.e(TAG, "Cannot bind to media container service");
 519                         for (HandlerParams params : mPendingInstalls) {
 520                             mPendingInstalls.remove(0);
 521                             // Indicate service bind error
 522                             params.serviceError();
 523                         }
 524                         mPendingInstalls.clear();
 525                     } else if (mPendingInstalls.size() > 0) {

                             // インストールキューの先頭分を処理
 526                         HandlerParams params = mPendingInstalls.get(0);
 527                         if (params != null) {
 528                             if (params.startCopy()) {
 529                                 // We are done...  look for more work or to
 530                                 // go idle.
 531                                 if (DEBUG_SD_INSTALL) Log.i(TAG,
 532                                         "Checking for more work or unbind...");
 533                                 // Delete pending install
 534                                 if (mPendingInstalls.size() > 0) {
 535                                     mPendingInstalls.remove(0);
 536                                 }
 537                                 if (mPendingInstalls.size() == 0) {
 538                                     if (mBound) {
 539                                         if (DEBUG_SD_INSTALL) Log.i(TAG,
 540                                                 "Posting delayed MCS_UNBIND");
 541                                         removeMessages(MCS_UNBIND);
                                              // キューが空になったら DefaultContainerService との接続を終了
 542                                         Message ubmsg = obtainMessage(MCS_UNBIND);
 543                                         // Unbind after a little delay, to avoid
 544                                         // continual thrashing.
 545                                         sendMessageDelayed(ubmsg, 10000);
 546                                     }
 547                                 } else {
                                         // まだキューにエントリがあれば MCS_BOUND メッセージを
                                         // 投げて次のエントリの処理へ
 548                                     // There are more pending requests in queue.
 549                                     // Just post MCS_BOUND message to trigger processing
 550                                     // of next pending install.
 551                                     if (DEBUG_SD_INSTALL) Log.i(TAG,
 552                                             "Posting MCS_BOUND for next woek");
 553                                     mHandler.sendEmptyMessage(MCS_BOUND);
 554                                 }
 555                             }
 556                         }
 557                     } else {
 558                         // Should never happen ideally.
 559                         Slog.w(TAG, "Empty queue");
 560                     }
 561                     break;
 562                 }
 563                 case MCS_RECONNECT: {
 564                     if (DEBUG_INSTALL) Slog.i(TAG, "mcs_reconnect");
 565                     if (mPendingInstalls.size() > 0) {
 566                         if (mBound) {
 567                             disconnectService();
 568                         }
 569                         if (!connectToService()) {
 570                             Slog.e(TAG, "Failed to bind to media container service");
 571                             for (HandlerParams params : mPendingInstalls) {
 572                                 mPendingInstalls.remove(0);
 573                                 // Indicate service bind error
 574                                 params.serviceError();
 575                             }
 576                             mPendingInstalls.clear();
 577                         }
 578                     }
 579                     break;
 580                 }
 581                 case MCS_UNBIND: {
 582                     // If there is no actual work left, then time to unbind.
 583                     if (DEBUG_INSTALL) Slog.i(TAG, "mcs_unbind");
 584 
                         // インストール待ちキューが空なら DefaultContainerService との接続を終了
 585                     if (mPendingInstalls.size() == 0 && mPendingVerification.size() == 0) {
 586                         if (mBound) {
 587                             if (DEBUG_INSTALL) Slog.i(TAG, "calling disconnectService()");
 588 
 589                             disconnectService();
 590                         }
 591                     } else if (mPendingInstalls.size() > 0) {
 592                         // There are more pending requests in queue.
 593                         // Just post MCS_BOUND message to trigger processing
 594                         // of next pending install.
 595                         mHandler.sendEmptyMessage(MCS_BOUND);
 596                     }
 597 
 598                     break;
 599                 }
 600                 case MCS_GIVE_UP: {
 601                     if (DEBUG_INSTALL) Slog.i(TAG, "mcs_giveup too many retries");
 602                     mPendingInstalls.remove(0);
 603                     break;
 604                 }
                              :

 655                 case POST_INSTALL: {
 656                     if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
 657                     PostInstallData data = mRunningInstalls.get(msg.arg1);
 658                     mRunningInstalls.delete(msg.arg1);
 659                     boolean deleteOld = false;
 660 
 661                     if (data != null) {
 662                         InstallArgs args = data.args;
 663                         PackageInstalledInfo res = data.res;
 664 
 665                         if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {

                                 // 処理成功なら完了通知をブロードキャスト
 666                             res.removedInfo.sendBroadcast(false, true);
 667                             Bundle extras = new Bundle(1);
 668                             extras.putInt(Intent.EXTRA_UID, res.uid);
 669                             final boolean update = res.removedInfo.removedPackage != null;
 670                             if (update) {
 671                                 extras.putBoolean(Intent.EXTRA_REPLACING, true);
 672                             }
 673                             sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
 674                                     res.pkg.applicationInfo.packageName,
 675                                     extras, null, null);
 676                             if (update) {
 677                                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
 678                                         res.pkg.applicationInfo.packageName,
 679                                         extras, null, null);
 680                                 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
 681                                         null, null,
 682                                         res.pkg.applicationInfo.packageName, null);
 683                             }
 684                             if (res.removedInfo.args != null) {
 685                                 // Remove the replaced package's older resources safely now
 686                                 deleteOld = true;
 687                             }
 688                         }
 689                         // Force a gc to clear up things
 690                         Runtime.getRuntime().gc();
 691                         // We delete after a gc for applications  on sdcard.
 692                         if (deleteOld) {
 693                             synchronized (mInstallLock) {
 694                                 res.removedInfo.args.doPostDeleteLI(true);
 695                             }
 696                         }

                             // 呼び元が installPackage() のコール時にオブザーバを指定していれば
                             // 完了の旨を伝える
 697                         if (args.observer != null) {
 698                             try {
 699                                 args.observer.packageInstalled(res.name, res.returnCode);
 700                             } catch (RemoteException e) {
 701                                 Slog.i(TAG, "Observer no longer exists.");
 702                             }
 703                         }
 704                     } else {
 705                         Slog.e(TAG, "Bogus post-install token " + msg.arg1);
 706                     }
 707                 } break;
                              :


4731     static final void sendPackageBroadcast(String action, String pkg,
4732             Bundle extras, String targetPkg, IIntentReceiver finishedReceiver) {
4733         IActivityManager am = ActivityManagerNative.getDefault();
4734         if (am != null) {
4735             try {
4736                 final Intent intent = new Intent(action,
4737                         pkg != null ? Uri.fromParts("package", pkg, null) : null);
4738                 if (extras != null) {
4739                     intent.putExtras(extras);
4740                 }
4741                 if (targetPkg != null) {
4742                     intent.setPackage(targetPkg);
4743                 }
4744                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
4745                 am.broadcastIntent(null, intent, null, finishedReceiver,
4746                         0, null, null, null, finishedReceiver != null, false);
4747             } catch (RemoteException ex) {
4748             }
4749         }
4750     }

frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より

抽象クラス HandlerParams

5223     private abstract class HandlerParams {
5224         private static final int MAX_RETRIES = 4;
5225 
5226         /**
5227          * Number of times startCopy() has been attempted and had a non-fatal
5228          * error.
5229          */
5230         private int mRetries = 0;
5231 
5232         final boolean startCopy() {
5233             boolean res;

                 // インストール対象 apk をインストール先へコピー
5234             try {
5235                 if (DEBUG_INSTALL) Slog.i(TAG, "startCopy");
5236 
                     // リトライオーバー
5237                 if (++mRetries > MAX_RETRIES) {
5238                     Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
5239                     mHandler.sendEmptyMessage(MCS_GIVE_UP); // ギブアップ
5240                     handleServiceError();
5241                     return false;
5242                 } else {
                         // コピー処理を呼ぶ
5243                     handleStartCopy();
5244                     res = true;
5245                 }
5246             } catch (RemoteException e) {
5247                 if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
                     // DefaultContainerService への接続をやり直し
5248                 mHandler.sendEmptyMessage(MCS_RECONNECT);
5249                 res = false;
5250             }
                 // handleStartCopy() の結果に基づいて後続処理を実施
5251             handleReturnCode();
5252             return res;
5253         }
5254 
5255         final void serviceError() {
5256             if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
5257             handleServiceError();
5258             handleReturnCode();
5259         }
5260 
5261         abstract void handleStartCopy() throws RemoteException;
5262         abstract void handleServiceError();
5263         abstract void handleReturnCode();
5264     }
                     :

InstallParams  -- HandlerParams の派生クラス

5338     class InstallParams extends HandlerParams {
5339         final IPackageInstallObserver observer;
5340         int flags;
5341         final Uri packageURI;
5342         final String installerPackageName;
5343         final Uri verificationURI;
5344         final ManifestDigest manifestDigest;
5345         private InstallArgs mArgs;
5346         private int mRet;
5347 
             // コンストラクタ
5348         InstallParams(Uri packageURI,
5349                 IPackageInstallObserver observer, int flags,
5350                 String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest) {
5351             this.packageURI = packageURI;
5352             this.flags = flags;
5353             this.observer = observer;
5354             this.installerPackageName = installerPackageName;
5355             this.verificationURI = verificationURI;
5356             this.manifestDigest = manifestDigest;
5357         }
5358 

             // インストールロケーションを判断
5359         private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
5360             String packageName = pkgLite.packageName;
5361             int installLocation = pkgLite.installLocation;
5362             boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
5363             // reader
5364             synchronized (mPackages) {
5365                 PackageParser.Package pkg = mPackages.get(packageName);
5366                 if (pkg != null) {
5367                     if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
5368                         // Check for updated system application.
5369                         if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
5370                             if (onSd) {
5371                                 Slog.w(TAG, "Cannot install update to system app on sdcard");
5372                                 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
5373                             }
5374                             return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
5375                         } else {
5376                             if (onSd) {
5377                                 // Install flag overrides everything.
5378                                 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5379                             }
5380                             // If current upgrade specifies particular preference
5381                             if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
5382                                 // Application explicitly specified internal.
5383                                 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
5384                             } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
5385                                 // App explictly prefers external. Let policy decide
5386                             } else {
5387                                 // Prefer previous location
5388                                 if (isExternal(pkg)) {
5389                                     return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5390                                 }
5391                                 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
5392                             }
5393                         }
5394                     } else {
5395                         // Invalid install. Return error code
5396                         return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
5397                     }
5398                 }
5399             }
5400             // All the special cases have been taken care of.
5401             // Return result based on recommended install location.
5402             if (onSd) {
5403                 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5404             }
5405             return pkgLite.recommendedInstallLocation;
5406         }
5407 
5408         /*
5409          * Invoke remote method to get package information and install
5410          * location values. Override install location based on default
5411          * policy if needed and then create install arguments based
5412          * on the install location.
5413          */
5414         public void handleStartCopy() throws RemoteException {
5415             int ret = PackageManager.INSTALL_SUCCEEDED;
5416             final boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
5417             final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
5418             final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
5419             PackageInfoLite pkgLite = null;
5420 
5421             if (onInt && onSd) { // 矛盾
5422                 // Check if both bits are set.
5423                 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
5424                 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
5425             } else if (fwdLocked && onSd) {// 矛盾
5426                 // Check for forward locked apps
5427                 Slog.w(TAG, "Cannot install fwd locked apps on sdcard");
5428                 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
5429             } else {
5430                 final long lowThreshold;
5431 
5432                 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
5433                         .getService(DeviceStorageMonitorService.SERVICE);
5434                 if (dsm == null) {
5435                     Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
5436                     lowThreshold = 0L;
5437                 } else {
5438                     lowThreshold = dsm.getMemoryLowThreshold();
5439                 }
5440 
5441                 // Remote call to find out default install location
5442                 try {
5443                     mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5444                             Intent.FLAG_GRANT_READ_URI_PERMISSION);
5445                     pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags,
5446                             lowThreshold);
5447                 } finally {
5448                     mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5449                 }
5450 
5451                 int loc = pkgLite.recommendedInstallLocation;
5452                 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
5453                     ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
5454                 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
5455                     ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5456                 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
5457                     ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5458                 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
5459                     ret = PackageManager.INSTALL_FAILED_INVALID_APK;
5460                 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
5461                     ret = PackageManager.INSTALL_FAILED_INVALID_URI;
5462                 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
5463                     ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
5464                 } else {
5465                     // Override with defaults if needed.
5466                     loc = installLocationPolicy(pkgLite, flags);
5467                     if (!onSd && !onInt) {
5468                         // Override install location with flags
5469                         if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
5470                             // Set the flag to install on external media.
5471                             flags |= PackageManager.INSTALL_EXTERNAL;
5472                             flags &= ~PackageManager.INSTALL_INTERNAL;
5473                         } else {
5474                             // Make sure the flag for installing on external
5475                             // media is unset
5476                             flags |= PackageManager.INSTALL_INTERNAL;
5477                             flags &= ~PackageManager.INSTALL_EXTERNAL;
5478                         }
5479                     }
5480                 }
5481             }
5482 
                 // インストールパラメータを構成
5483             final InstallArgs args = createInstallArgs(this);
5484             mArgs = args;
5485 
5486             if (ret == PackageManager.INSTALL_SUCCEEDED) {
5487                 /*
5488                  * Determine if we have any installed package verifiers. If we
5489                  * do, then we'll defer to them to verify the packages.
5490                  */
5491                 final int requiredUid = mRequiredVerifierPackage == null ? -1
5492                         : getPackageUid(mRequiredVerifierPackage);
5493                 if (requiredUid != -1 && isVerificationEnabled()) {
                                           :

5578                 } else {
                         // 当該 apk をインストール先へ一時ファイル名でコピー
5579                     /*
5580                      * No package verification is enabled, so immediately start
5581                      * the remote call to initiate copy using temporary file.
5582                      */
5583                     ret = args.copyApk(mContainerService, true);
5584                 }
5585             }
5586 
5587             mRet = ret;
5588         }
5589 

5590         @Override
5591         void handleReturnCode() {
5592             // If mArgs is null, then MCS couldn't be reached. When it
5593             // reconnects, it will try again to install. At that point, this
5594             // will succeed.
5595             if (mArgs != null) {
5596                 processPendingInstall(mArgs, mRet);
5597             }
5598         }
                     :

5678     private InstallArgs createInstallArgs(InstallParams params) {
             //(筆者注:以降の SD カードへのインストール処理の引用は省きます)
5679         if (installOnSd(params.flags)) {
5680             return new SdInstallArgs(params);
5681         } else {
5682             return new FileInstallArgs(params);
5683         }
5684     }
                     :
frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より

抽象クラス InstallArgs

5705     static abstract class InstallArgs {
5706         final IPackageInstallObserver observer;
5707         // Always refers to PackageManager flags only
5708         final int flags;
5709         final Uri packageURI;
5710         final String installerPackageName;
5711         final ManifestDigest manifestDigest;
5712 
5713         InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
5714                 String installerPackageName, ManifestDigest manifestDigest) {
5715             this.packageURI = packageURI;
5716             this.flags = flags;
5717             this.observer = observer;
5718             this.installerPackageName = installerPackageName;
5719             this.manifestDigest = manifestDigest;
5720         }
5721 
5722         abstract void createCopyFile();
5723         abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
5724         abstract int doPreInstall(int status);
5725         abstract boolean doRename(int status, String pkgName, String oldCodePath);
5726         abstract int doPostInstall(int status);
5727         abstract String getCodePath();
5728         abstract String getResourcePath();
5729         abstract String getNativeLibraryPath();
5730         // Need installer lock especially for dex file removal.
5731         abstract void cleanUpResourcesLI();
5732         abstract boolean doPostDeleteLI(boolean delete);
5733         abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
5734     }
5735 

FileInstallArgs  -- InstallArgs の派生クラス

5736     class FileInstallArgs extends InstallArgs {
5737         File installDir;
5738         String codeFileName;
5739         String resourceFileName;
5740         String libraryPath;
5741         boolean created = false;
5742 

             // コンストラクタ
5743         FileInstallArgs(InstallParams params) {
5744             super(params.packageURI, params.observer, params.flags, params.installerPackageName,
5745                     params.manifestDigest);
5746         }
                  :

            // インストール先ディレクトリ下での一時ファイル名を作成
5796         void createCopyFile() {
5797             installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
5798             codeFileName = createTempPackageFile(installDir).getPath();
5799             resourceFileName = getResourcePathFromCodePath();
5800             created = true;
5801         }
5802 

             // インストール先ディレクトリへ当該 apk を一時ファイル名でコピーする
5803         int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
5804             if (temp) {
5805                 // Generate temp file name
5806                 createCopyFile(); // 一時ファイル名を codeFileName にセット
5807             }
5808             // Get a ParcelFileDescriptor to write to the output file
5809             File codeFile = new File(codeFileName);
5810             if (!created) {
5811                 try {
5812                     codeFile.createNewFile();
5813                     // Set permissions
5814                     if (!setPermissions()) {
5815                         // Failed setting permissions.
5816                         return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5817                     }
5818                 } catch (IOException e) {
5819                    Slog.w(TAG, "Failed to create file " + codeFile);
5820                    return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5821                 }
5822             }
5823             ParcelFileDescriptor out = null;
5824             try {
5825                 out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
5826             } catch (FileNotFoundException e) {
5827                 Slog.e(TAG, "Failed to create file descriptor for : " + codeFileName);
5828                 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5829             }
5830             // Copy the resource now
5831             int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5832             try {
5833                 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5834                         Intent.FLAG_GRANT_READ_URI_PERMISSION);

                     // DefaultContainerService を利用してリソースをコピー
5835                 ret = imcs.copyResource(packageURI, out);
5836             } finally {
5837                 try { if (out != null) out.close(); } catch (IOException e) {}
5838                 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5839             }
5840 
5841             return ret;
5842         }
5843 
             // インストール前処理
5844         int doPreInstall(int status) {
5845             if (status != PackageManager.INSTALL_SUCCEEDED) {
5846                 cleanUp();
5847             }
5848             return status;
5849         }
5850 

             // apk のリネーム
5851         boolean doRename(int status, final String pkgName, String oldCodePath) {
5852             if (status != PackageManager.INSTALL_SUCCEEDED) {
5853                 cleanUp();
5854                 return false;
5855             } else {
5856                 // Rename based on packageName
5857                 File codeFile = new File(getCodePath());
5858                 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
5859                 File desFile = new File(installDir, apkName + ".apk");
5860                 if (!codeFile.renameTo(desFile)) {
5861                     return false;
5862                 }
5863                 // Reset paths since the file has been renamed.
5864                 codeFileName = desFile.getPath();
5865                 resourceFileName = getResourcePathFromCodePath();
5866                 // Set permissions
5867                 if (!setPermissions()) {
5868                     // Failed setting permissions.
5869                     return false;
5870                 }
5871                 return true;
5872             }
5873         }
5874 

             // インストール後処理
5875         int doPostInstall(int status) {
5876             if (status != PackageManager.INSTALL_SUCCEEDED) {
5877                 cleanUp();
5878             }
5879             return status;
5880         }
5881 
5882         String getResourcePath() {
5883             return resourceFileName;
5884         }
5885 
5886         String getResourcePathFromCodePath() {
5887             String codePath = getCodePath();
5888             if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
5889                 String apkNameOnly = getApkName(codePath);
5890                 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
5891             } else {
5892                 return codePath;
5893             }
5894         }
5895 
5896         @Override
5897         String getNativeLibraryPath() {
5898             return libraryPath;
5899         }
5900 
5901         private boolean cleanUp() {
5902             boolean ret = true;
5903             String sourceDir = getCodePath();
5904             String publicSourceDir = getResourcePath();
5905             if (sourceDir != null) {
5906                 File sourceFile = new File(sourceDir);
5907                 if (!sourceFile.exists()) {
5908                     Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
5909                     ret = false;
5910                 }
5911                 // Delete application's code and resources
5912                 sourceFile.delete();
5913             }
5914             if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
5915                 final File publicSourceFile = new File(publicSourceDir);
5916                 if (!publicSourceFile.exists()) {
5917                     Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
5918                 }
5919                 if (publicSourceFile.exists()) {
5920                     publicSourceFile.delete();
5921                 }
5922             }
5923             return ret;
5924         }
5925 
5926         void cleanUpResourcesLI() {
5927             String sourceDir = getCodePath();
5928             if (cleanUp()) {
5929                 int retCode = mInstaller.rmdex(sourceDir);
5930                 if (retCode < 0) {
5931                     Slog.w(TAG, "Couldn't remove dex file for package: "
5932                             +  " at location "
5933                             + sourceDir + ", retcode=" + retCode);
5934                     // we don't consider this to be a failure of the core package deletion
5935                 }
5936             }
5937         }
5938 
5939         private boolean setPermissions() {
5940             // TODO Do this in a more elegant way later on. for now just a hack
5941             if (!isFwdLocked()) {
5942                 final int filePermissions =
5943                     FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
5944                     |FileUtils.S_IROTH;
5945                 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
5946                 if (retCode != 0) {
5947                     Slog.e(TAG, "Couldn't set new package file permissions for " +
5948                             getCodePath()
5949                             + ". The return code was: " + retCode);
5950                     // TODO Define new internal error
5951                     return false;
5952                 }
5953                 return true;
5954             }
5955             return true;
5956         }
5957 
5958         boolean doPostDeleteLI(boolean delete) {
5959             // XXX err, shouldn't we respect the delete flag?
5960             cleanUpResourcesLI();
5961             return true;
5962         }
5963 
5964         private boolean isFwdLocked() {
5965             return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
5966         }
5967     }
                      :
frameworks/base/core/java/com/android/internal/app/IMediaContainerService.aidl より

  17 package com.android.internal.app;
                  :

  24 interface IMediaContainerService {
  25     String copyResourceToContainer(in Uri packageURI,
  26                 String containerId,
  27                 String key, String resFileName);
  28     int copyResource(in Uri packageURI,
  29                 in ParcelFileDescriptor outStream);
  30     PackageInfoLite getMinimalPackageInfo(in Uri fileUri, in int flags, in long threshold);
  31     boolean checkInternalFreeStorage(in Uri fileUri, in long threshold);
  32     boolean checkExternalFreeStorage(in Uri fileUri);
  33     ObbInfo getObbInfo(in String filename);
  34     long calculateDirectorySize(in String directory);
  35 }
frameworks/base/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java より
DefaultContainerService クラス

  17 package com.android.defcontainer;
                        :

  53 /*
  54  * This service copies a downloaded apk to a file passed in as
  55  * a ParcelFileDescriptor or to a newly created container specified
  56  * by parameters. The DownloadManager gives access to this process
  57  * based on its uid. This process also needs the ACCESS_DOWNLOAD_MANAGER
  58  * permission to access apks downloaded via the download manager.
  59  */
  60 public class DefaultContainerService extends IntentService {
  61     private static final String TAG = "DefContainer";
  62     private static final boolean localLOGV = true;
  63 
  64     private static final String LIB_DIR_NAME = "lib";
  65 
  66     private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {
  67         /*
  68          * Creates a new container and copies resource there.
  69          * @param paackageURI the uri of resource to be copied. Can be either
  70          * a content uri or a file uri
  71          * @param cid the id of the secure container that should
  72          * be used for creating a secure container into which the resource
  73          * will be copied.
  74          * @param key Refers to key used for encrypting the secure container
  75          * @param resFileName Name of the target resource file(relative to newly
  76          * created secure container)
  77          * @return Returns the new cache path where the resource has been copied into
  78          *
  79          */                        :

  90          * Copy specified resource to output stream
  91          * @param packageURI the uri of resource to be copied. Should be a file
  92          * uri
  93          * @param outStream Remote file descriptor to be used for copying
  94          * @return returns status code according to those in {@link
  95          * PackageManager}
  96          */
  97         public int copyResource(final Uri packageURI, ParcelFileDescriptor outStream) {
  98             if (packageURI == null || outStream == null) {
  99                 return PackageManager.INSTALL_FAILED_INVALID_URI;
 100             }
 101 
 102             ParcelFileDescriptor.AutoCloseOutputStream autoOut
 103                     = new ParcelFileDescriptor.AutoCloseOutputStream(outStream);
 104 
 105             try {
 106                 copyFile(packageURI, autoOut);
 107                 return PackageManager.INSTALL_SUCCEEDED;
 108             } catch (FileNotFoundException e) {
 109                 Slog.e(TAG, "Could not copy URI " + packageURI.toString() + " FNF: "
 110                         + e.getMessage());
 111                 return PackageManager.INSTALL_FAILED_INVALID_URI;
 112             } catch (IOException e) {
 113                 Slog.e(TAG, "Could not copy URI " + packageURI.toString() + " IO: "
 114                         + e.getMessage());
 115                 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
 116             }
 117         }
                         :
 206     };

 332     private static void copyToFile(InputStream inputStream, OutputStream out) throws IOException {
 333         byte[] buffer = new byte[16384];
 334         int bytesRead;
 335         while ((bytesRead = inputStream.read(buffer)) >= 0) {
 336             out.write(buffer, 0, bytesRead);
 337         }
 338     }
 339 
 340     private static void copyToFile(File srcFile, OutputStream out)
 341             throws FileNotFoundException, IOException {
 342         InputStream inputStream = new BufferedInputStream(new FileInputStream(srcFile));
 343         try {
 344             copyToFile(inputStream, out);
 345         } finally {
 346             try { inputStream.close(); } catch (IOException e) {}
 347         }
 348     }
 349 
 350     private void copyFile(Uri pPackageURI, OutputStream outStream) throws FileNotFoundException,
 351             IOException {
 352         String scheme = pPackageURI.getScheme();

             // スキームごとに処理
 353         if (scheme == null || scheme.equals("file")) {
 354             final File srcPackageFile = new File(pPackageURI.getPath());
 355             // We copy the source package file to a temp file and then rename it to the
 356             // destination file in order to eliminate a window where the package directory
 357             // scanner notices the new package file but it's not completely copied yet.
 358             copyToFile(srcPackageFile, outStream);
 359         } else if (scheme.equals("content")) {
 360             ParcelFileDescriptor fd = null;
 361             try {
 362                 fd = getContentResolver().openFileDescriptor(pPackageURI, "r");
 363             } catch (FileNotFoundException e) {
 364                 Slog.e(TAG, "Couldn't open file descriptor from download service. "
 365                         + "Failed with exception " + e);
 366                 throw e;
 367             }
 368 
 369             if (fd == null) {
 370                 Slog.e(TAG, "Provider returned no file descriptor for " + pPackageURI.toString());
 371                 throw new FileNotFoundException("provider returned no file descriptor");
 372             } else {
 373                 if (localLOGV) {
 374                     Slog.i(TAG, "Opened file descriptor from download service.");
 375                 }
 376                 ParcelFileDescriptor.AutoCloseInputStream dlStream
 377                         = new ParcelFileDescriptor.AutoCloseInputStream(fd);
 378 
 379                 // We copy the source package file to a temp file and then rename it to the
 380                 // destination file in order to eliminate a window where the package directory
 381                 // scanner notices the new package file but it's not completely
 382                 // copied
 383                 copyToFile(dlStream, outStream);
 384             }
 385         } else {
 386             Slog.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
 387             throw new FileNotFoundException("Package URI is not 'file:' or 'content:'");
 388         }
 389     }
                          :
frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より

         // インストールの実処理呼び出し〜完了を通知
5150     private void processPendingInstall(final InstallArgs args, final int currentStatus) {
5151         // Queue up an async operation since the package installation may take a little while.
5152         mHandler.post(new Runnable() {
5153             public void run() {
5154                 mHandler.removeCallbacks(this);
5155                  // Result object to be returned
5156                 PackageInstalledInfo res = new PackageInstalledInfo();
5157                 res.returnCode = currentStatus;
5158                 res.uid = -1;
5159                 res.pkg = null;
5160                 res.removedInfo = new PackageRemovedInfo();

                     // インストール!
5161                 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
5162                     args.doPreInstall(res.returnCode);
5163                     synchronized (mInstallLock) {
5164                         installPackageLI(args, true, res);
5165                     }
5166                     args.doPostInstall(res.returnCode);
5167                 }
5168 
5169                 // A restore should be performed at this point if (a) the install
5170                 // succeeded, (b) the operation is not an update, and (c) the new
5171                 // package has a backupAgent defined.
5172                 final boolean update = res.removedInfo.removedPackage != null;
5173                 boolean doRestore = (!update
5174                         && res.pkg != null
5175                         && res.pkg.applicationInfo.backupAgentName != null);
5176 
5177                 // Set up the post-install work request bookkeeping.  This will be used
5178                 // and cleaned up by the post-install event handling regardless of whether
5179                 // there's a restore pass performed.  Token values are >= 1.
5180                 int token;
5181                 if (mNextInstallToken < 0) mNextInstallToken = 1;
5182                 token = mNextInstallToken++;
5183 
5184                 PostInstallData data = new PostInstallData(args, res);
5185                 mRunningInstalls.put(token, data);
5186                 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
5187 
5188                 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
5189                     // Pass responsibility to the Backup Manager.  It will perform a
5190                     // restore if appropriate, then pass responsibility back to the
5191                     // Package Manager to run the post-install observer callbacks
5192                     // and broadcasts.
5193                     IBackupManager bm = IBackupManager.Stub.asInterface(
5194                             ServiceManager.getService(Context.BACKUP_SERVICE));
5195                     if (bm != null) {
5196                         if (DEBUG_INSTALL) Log.v(TAG, "token " + token
5197                                 + " to BM for possible restore");
5198                         try {
5199                             bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
5200                         } catch (RemoteException e) {
5201                             // can't happen; the backup manager is local
5202                         } catch (Exception e) {
5203                             Slog.e(TAG, "Exception trying to enqueue restore", e);
5204                             doRestore = false;
5205                         }
5206                     } else {
5207                         Slog.e(TAG, "Backup Manager not found!");
5208                         doRestore = false;
5209                     }
5210                 }
5211 
5212                 if (!doRestore) {
5213                     // No restore possible, or the Backup Manager was mysteriously not
5214                     // available -- just fire the post-install work request directly.
5215                     if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);

                         // メッセージハンドラへ完了通知を送る
5216                     Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
5217                     mHandler.sendMessage(msg);
5218                 }
5219             }
5220         });
5221     }
                          :
frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より

         // インストール実処理
6594     private void installPackageLI(InstallArgs args,
6595             boolean newInstall, PackageInstalledInfo res) {
6596         int pFlags = args.flags;
6597         String installerPackageName = args.installerPackageName;
6598         File tmpPackageFile = new File(args.getCodePath());
6599         boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
6600         boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
6601         boolean replace = false;
6602         int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
6603                 | (newInstall ? SCAN_NEW_INSTALL : 0);
6604         // Result object to be returned
6605         res.returnCode = PackageManager.INSTALL_SUCCEEDED;
6606 
6607         // Retrieve PackageSettings and parse package
6608         int parseFlags = PackageParser.PARSE_CHATTY |
6609         (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
6610         (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
6611         parseFlags |= mDefParseFlags;
6612         PackageParser pp = new PackageParser(tmpPackageFile.getPath());
6613         pp.setSeparateProcesses(mSeparateProcesses);

             // パッケージの情報を得る
6614         final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
6615                 null, mMetrics, parseFlags);
6616         if (pkg == null) {
6617             res.returnCode = pp.getParseError();
6618             return;
6619         }
6620         String pkgName = res.name = pkg.packageName;
6621         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
6622             if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
6623                 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
6624                 return;
6625             }
6626         }
6627         if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
6628             res.returnCode = pp.getParseError();
6629             return;
6630         }
6631 
6632         /* If the installer passed in a manifest digest, compare it now. */
6633         if (args.manifestDigest != null) {
6634             if (DEBUG_INSTALL) {
6635                 final String parsedManifest = pkg.manifestDigest == null ? "null"
6636                         : pkg.manifestDigest.toString();
6637                 Slog.d(TAG, "Comparing manifests: " + args.manifestDigest.toString() + " vs. "
6638                         + parsedManifest);
6639             }
6640 
6641             if (!args.manifestDigest.equals(pkg.manifestDigest)) {
6642                 res.returnCode = PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
6643                 return;
6644             }
6645         } else if (DEBUG_INSTALL) {
6646             final String parsedManifest = pkg.manifestDigest == null
6647                     ? "null" : pkg.manifestDigest.toString();
6648             Slog.d(TAG, "manifestDigest was not present, but parser got: " + parsedManifest);
6649         }
6650 
6651         // Get rid of all references to package scan path via parser.
6652         pp = null;
6653         String oldCodePath = null;
6654         boolean systemApp = false;
6655         synchronized (mPackages) {
6656             // Check if installing already existing package
6657             if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
6658                 String oldName = mSettings.mRenamedPackages.get(pkgName);
6659                 if (pkg.mOriginalPackages != null
6660                         && pkg.mOriginalPackages.contains(oldName)
6661                         && mPackages.containsKey(oldName)) {
6662                     // This package is derived from an original package,
6663                     // and this device has been updating from that original
6664                     // name.  We must continue using the original name, so
6665                     // rename the new package here.
6666                     pkg.setPackageName(oldName);
6667                     pkgName = pkg.packageName;
6668                     replace = true;
6669                 } else if (mPackages.containsKey(pkgName)) {
6670                     // This package, under its official name, already exists
6671                     // on the device; we should replace it.
6672                     replace = true;
6673                 }
6674             }
6675             PackageSetting ps = mSettings.mPackages.get(pkgName);
6676             if (ps != null) {
6677                 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
6678                 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
6679                     systemApp = (ps.pkg.applicationInfo.flags &
6680                             ApplicationInfo.FLAG_SYSTEM) != 0;
6681                 }
6682             }
6683         }
6684 
6685         if (systemApp && onSd) {
6686             // Disable updates to system apps on sdcard
6687             Slog.w(TAG, "Cannot install updates to system apps on sdcard");
6688             res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
6689             return;
6690         }
6691 
             // インストール先へ一時ファイル名でコピーずみの apk をパッケージ名にリネーム
6692         if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
6693             res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6694             return;
6695         }
6696         // Set application objects path explicitly after the rename
6697         setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
6698         pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();

             //(筆者注:以降の更新インストール処理の引用は省きます)
6699         if (replace) {
6700             replacePackageLI(pkg, parseFlags, scanMode,
6701                     installerPackageName, res);
6702         } else {
6703             installNewPackageLI(pkg, parseFlags, scanMode,
6704                     installerPackageName,res);
6705         }
6706     }
                      :
frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より

         // 新規インストール処理
6280     /*
6281      * Install a non-existing package.
6282      */
6283     private void installNewPackageLI(PackageParser.Package pkg,
6284             int parseFlags,
6285             int scanMode,
6286             String installerPackageName, PackageInstalledInfo res) {
6287         // Remember this for later, in case we need to rollback this install
6288         String pkgName = pkg.packageName;
6289 
6290         boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
6291         res.name = pkgName;
6292         synchronized(mPackages) {
6293             if (mSettings.mRenamedPackages.containsKey(pkgName)) {
6294                 // A package with the same name is already installed, though
6295                 // it has been renamed to an older name.  The package we
6296                 // are trying to install should be installed as an update to
6297                 // the existing one, but that has not been requested, so bail.
6298                 Slog.w(TAG, "Attempt to re-install " + pkgName
6299                         + " without first uninstalling package running as "
6300                         + mSettings.mRenamedPackages.get(pkgName));
6301                 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
6302                 return;
6303             }
6304             if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
6305                 // Don't allow installation over an existing package with the same name.
6306                 Slog.w(TAG, "Attempt to re-install " + pkgName
6307                         + " without first uninstalling.");
6308                 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
6309                 return;
6310             }
6311         }
6312         mLastScanError = PackageManager.INSTALL_SUCCEEDED;

             // 当該パッケージのデータディレクトリを作成しあらためて
             // パッケージ情報を得る。エラーがあれば返値は null
6313         PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
6314                 System.currentTimeMillis());
6315         if (newPackage == null) { // NG
6316             Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
6317             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
6318                 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
6319             }
6320         } else {
                 // OK! packages.xml の更新処理へ
6321             updateSettingsLI(newPackage,
6322                     installerPackageName,
6323                     res);
6324             // delete the partially installed application. the data directory will have to be
6325             // restored if it was already existing
6326             if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
6327                 // remove package from internal structures.  Note that we want deletePackageX to
6328                 // delete the package data and cache directories that it created in
6329                 // scanPackageLocked, unless those directories existed before we even tried to
6330                 // install.
6331                 deletePackageLI(
6332                         pkgName, false,
6333                         dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
6334                                 res.removedInfo, true);
6335             }
6336         }
6337     }
                      :
frameworks/base/services/java/com/android/server/pm/PackageManagerService.java より

         // インストール処理の最後に packages.xml を更新するための手続き
6557     private void updateSettingsLI(PackageParser.Package newPackage,
6558             String installerPackageName, PackageInstalledInfo res) {
6559         String pkgName = newPackage.packageName;
6560         synchronized (mPackages) {

                 // 最終処理で失敗する可能性を見こしての仮更新
6561             //write settings. the installStatus will be incomplete at this stage.
6562             //note that the new package setting would have already been
6563             //added to mPackages. It hasn't been persisted yet.
6564             mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE);
6565             mSettings.writeLPr();
6566         }
6567 
             // パッケージの dex ファイルを正規の場所へ
6568         if ((res.returnCode = moveDexFilesLI(newPackage))
6569                 != PackageManager.INSTALL_SUCCEEDED) {
6570             // Discontinue if moving dex files failed.
6571             return;
6572         }

             // 必要があれば apk に所定のファイルパーミッションを設定
6573         if((res.returnCode = setPermissionsLI(newPackage))
6574                 != PackageManager.INSTALL_SUCCEEDED) {
6575             mInstaller.rmdex(newPackage.mScanPath);
6576             return;
6577         } else {
6578             Log.d(TAG, "New package installed in " + newPackage.mPath);
6579         }

             // /data/system/packages.xml と packages.list を正式に更新
6580         synchronized (mPackages) {
6581             updatePermissionsLPw(newPackage.packageName, newPackage,
6582                     newPackage.permissions.size() > 0, true, false);
6583             res.name = pkgName;
6584             res.uid = newPackage.applicationInfo.uid;
6585             res.pkg = newPackage;
6586             mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
6587             mSettings.setInstallerPackageName(pkgName, installerPackageName);
6588             res.returnCode = PackageManager.INSTALL_SUCCEEDED;
6589             //to update install status
6590             mSettings.writeLPr();
6591         }
6592     }
                     :

         // dex ファイルを正規のロケーションへ移動
6535     // Utility method used to move dex files during install.
6536     private int moveDexFilesLI(PackageParser.Package newPackage) {
6537         int retCode;
6538         if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
6539             retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
6540             if (retCode != 0) {
6541                 if (mNoDexOpt) {
6542                     /*
6543                      * If we're in an engineering build, programs are lazily run
6544                      * through dexopt. If the .dex file doesn't exist yet, it
6545                      * will be created when the program is run next.
6546                      */
6547                     Slog.i(TAG, "dex file doesn't exist, skipping move: " + newPackage.mPath);
6548                 } else {
6549                     Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
6550                     return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6551                 }
6552             }
6553         }
6554         return PackageManager.INSTALL_SUCCEEDED;
6555     }
6556 
                     :


         // 必要なファイルパーミッションを apk に設定
6708     private int setPermissionsLI(PackageParser.Package newPackage) {
6709         int retCode = 0;
6710         // TODO Gross hack but fix later. Ideally move this to be a post installation
6711         // check after alloting uid.

             // ここでの対象はフォワードロックされた apk のみ
6712         if (isForwardLocked(newPackage)) {
6713             File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
6714             try {
6715                 extractPublicFiles(newPackage, destResourceFile);
6716             } catch (IOException e) {
6717                 Slog.e(TAG, "Couldn't create a new zip file for the public parts of a" +
6718                            " forward-locked app.");
6719                 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6720             } finally {
6721                 //TODO clean up the extracted public files
6722             }
6723             retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
6724                     newPackage.applicationInfo.uid);
6725         } else {
6726             // The permissions on the resource file was set when it was copied for
6727             // non forward locked apps and apps on sdcard
6728         }
6729 
6730         if (retCode != 0) {
6731             Slog.e(TAG, "Couldn't set new package file permissions for " + newPackage.mPath
6732                     + ". The return code was: " + retCode);
6733             // TODO Define new internal error
6734             return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6735         }
6736         return PackageManager.INSTALL_SUCCEEDED;
6737     }
                     :

(tanabe)
klab_gijutsu2 at 12:45│Comments(2)Android | win

この記事へのコメント

1. Posted by hal   2012年12月28日 17:58
5 /system/data/packages.xmlは/data/system/packages.xmlが正しいような気がします。
/system下では更新できないような。
4.0.4 の実機では/data/systemでした。
2. Posted by tanabe   2012年12月28日 19:16
hal さん、コメントをありがとうございます。修正しておきますね。

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント