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.rc ■ PackageManagerService のスタートアップ - 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 IteratordisabledIt = 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)
この記事へのコメント
/system下では更新できないような。
4.0.4 の実機では/data/systemでした。