PackageManager 分析(1)
- packages\apps\PackageInstaller 代码分析
涉及到的主要代码
应用层代码
/packages/apps/PackageInstaller/*
供应用调用的framework代码
frameworks/base/core$ find ./ -name ApplicationPackageManager*
./java/android/app/ApplicationPackageManager.java
/frameworks/base$ find ./ -name PackageInstaller*
./core/java/android/content/pm/PackageInstaller.aidl
./core/java/android/content/pm/PackageInstaller.java
service服务层代码
./services/core/java/com/android/server/pm/PackageInstallerService.java
./services/core/java/com/android/server/pm/PackageInstallerSession.java
1.1 packageInstallerActivity.java
1.1.1 AndroidManifest.xml
查看AndroidManifest.xml文件中的packageInstallerActivity 对应的 intent-filter, 可以知道有几种启动方式
第三方APK通过发送隐式的intent 去启动packageInstallerActivity。
当贝APK安装第三方应用的日志
12-16 14:41:22.959 I/ActivityManager( 4279): START u0 {act=android.intent.action.VIEW dat=file:///storage/emulated/0/Download/3ub1cmbq4yl96yevi48a6spmtaq2ytv7.11dangbei.dangbei typ=application/vnd.android.package-archive flg=0x10000000 cmp=com.google.android.packageinstaller/com.android.packageinstaller.PackageInstallerActivity} from uid 10066 on display 0
AndroidManifest.xml
<activity android:name=".PackageInstallerActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:excludeFromRecents="true">
<intent-filter android:priority="1">
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.INSTALL_PACKAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:mimeType="application/vnd.android.package-archive" />
</intent-filter>
<intent-filter android:priority="1">
<action android:name="android.intent.action.INSTALL_PACKAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:scheme="package" />
<data android:scheme="content" />
</intent-filter>
<intent-filter android:priority="1">
<action android:name="android.content.pm.action.CONFIRM_PERMISSIONS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
1.1.2 packageInstallerActivity
通过final Intent intent = getIntent();获取APK的URI信息。然后做了些activity加载相关的工作。
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
mPm = getPackageManager(); /**/
mInstaller = mPm.getPackageInstaller();
mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
final Intent intent = getIntent();
mOriginatingUid = getOriginatingUid(intent);
final Uri packageUri;
if (PackageInstaller.ACTION_CONFIRM_PERMISSIONS.equals(intent.getAction())) {
final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId);
if (info == null || !info.sealed || info.resolvedBaseCodePath == null) {
Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
finish();
return;
}
mSessionId = sessionId;
packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath));
mOriginatingURI = null;
mReferrerURI = null;
} else {
mSessionId = -1;
packageUri = intent.getData();
mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
}
// if there's nothing to do, quietly slip into the ether
if (packageUri == null) {
Log.w(TAG, "Unspecified source");
setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
finish();
return;
}
if (DeviceUtils.isWear(this)) {
showDialogInner(DLG_NOT_SUPPORTED_ON_WEAR);
return;
}
//set view
setContentView(R.layout.install_start);
mInstallConfirm = findViewById(R.id.install_confirm_panel);
mInstallConfirm.setVisibility(View.INVISIBLE);
mOk = (Button)findViewById(R.id.ok_button);
mCancel = (Button)findViewById(R.id.cancel_button);
mOk.setOnClickListener(this);
mCancel.setOnClickListener(this);
boolean wasSetUp = processPackageUri(packageUri);
if (!wasSetUp) {
return;
}
checkIfAllowedAndInitiateInstall(false);
}
checkIfAllowedAndInitiateInstall 判断是否容许第三方来源的APK安装。如果不容许未知来源的APK安装,则显示提示框。
/**
* Check if it is allowed to install the package and initiate install if allowed. If not allowed
* show the appropriate dialog.
*
* @param ignoreUnknownSourcesSettings Ignore {@link #isUnknownSourcesEnabled()} and proceed
* even if this would prevented installation.
*/
private void checkIfAllowedAndInitiateInstall(boolean