Handle pre-commit install session in PackageInstaller (3/n)

Since developers now could request a pre-commit install session
without APK files, PackageInstaller would need to support this
new use case.

Bug: 242677131
Test: atest CtsPackageInstallTestCases
Change-Id: I5da9504b0626b7fb81acb664d51df6de8c866ea2
This commit is contained in:
Jackal Guo
2022-09-06 13:25:11 +08:00
parent b0ff86efa9
commit cdcf25b0cd
3 changed files with 74 additions and 11 deletions

View File

@@ -59,6 +59,10 @@
<action android:name="android.content.pm.action.CONFIRM_INSTALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="1">
<action android:name="android.content.pm.action.CONFIRM_PRE_APPROVAL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".InstallStaging"

View File

@@ -59,7 +59,8 @@ public class InstallStart extends Activity {
String callingAttributionTag = null;
final boolean isSessionInstall =
PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction());
PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL.equals(intent.getAction())
|| PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction());
// If the activity was started via a PackageInstaller session, we retrieve the calling
// package from that session

View File

@@ -39,9 +39,11 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
@@ -151,7 +153,7 @@ public class PackageInstallerActivity extends AlertActivity {
}
/**
* Replace any dialog shown by the dialog with the one for the given {@link #createDialog id}.
* Replace any dialog shown by the dialog with the one for the given {@link #createDialog(int)}.
*
* @param id The dialog type to add
*/
@@ -296,6 +298,14 @@ public class PackageInstallerActivity extends AlertActivity {
? RESULT_OK : RESULT_FIRST_USER, result);
}
private static PackageInfo generateStubPackageInfo(String packageName) {
final PackageInfo info = new PackageInfo();
final ApplicationInfo aInfo = new ApplicationInfo();
info.applicationInfo = aInfo;
info.packageName = info.applicationInfo.packageName = packageName;
return info;
}
@Override
protected void onCreate(Bundle icicle) {
if (mLocalLOGV) Log.i(TAG, "creating for user " + getUserId());
@@ -315,6 +325,7 @@ public class PackageInstallerActivity extends AlertActivity {
mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
final Intent intent = getIntent();
final String action = intent.getAction();
mCallingPackage = intent.getStringExtra(EXTRA_CALLING_PACKAGE);
mCallingAttributionTag = intent.getStringExtra(EXTRA_CALLING_ATTRIBUTION_TAG);
@@ -324,11 +335,11 @@ public class PackageInstallerActivity extends AlertActivity {
mOriginatingPackage = (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN)
? getPackageNameForUid(mOriginatingUid) : null;
final Uri packageUri;
if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) {
final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId);
final Object packageSource;
if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(action)) {
final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID,
-1 /* defaultValue */);
final SessionInfo info = mInstaller.getSessionInfo(sessionId);
if (info == null || !info.sealed || info.resolvedBaseCodePath == null) {
Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
finish();
@@ -336,18 +347,32 @@ public class PackageInstallerActivity extends AlertActivity {
}
mSessionId = sessionId;
packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath));
packageSource = Uri.fromFile(new File(info.resolvedBaseCodePath));
mOriginatingURI = null;
mReferrerURI = null;
} else if (PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL.equals(action)) {
final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID,
-1 /* defaultValue */);
final SessionInfo info = mInstaller.getSessionInfo(sessionId);
if (info == null || !info.isPreapprovalRequested) {
Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
finish();
return;
}
mSessionId = sessionId;
packageSource = info;
mOriginatingURI = null;
mReferrerURI = null;
} else {
mSessionId = -1;
packageUri = intent.getData();
packageSource = 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) {
if (packageSource == null) {
Log.w(TAG, "Unspecified source");
setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
finish();
@@ -359,7 +384,7 @@ public class PackageInstallerActivity extends AlertActivity {
return;
}
boolean wasSetUp = processPackageUri(packageUri);
final boolean wasSetUp = processAppSnippet(packageSource);
if (mLocalLOGV) Log.i(TAG, "wasSetUp: " + wasSetUp);
if (!wasSetUp) {
@@ -619,6 +644,39 @@ public class PackageInstallerActivity extends AlertActivity {
return true;
}
/**
* Use the SessionInfo and set up the installer for pre-commit install session.
*
* @param info The SessionInfo to compose
*
* @return {@code true} iff the installer could be set up
*/
private boolean processSessionInfo(@NonNull SessionInfo info) {
mPkgInfo = generateStubPackageInfo(info.appPackageName);
mAppSnippet = new PackageUtil.AppSnippet(info.appLabel,
info.appIcon != null ? new BitmapDrawable(getResources(), info.appIcon)
: getPackageManager().getDefaultActivityIcon());
return true;
}
/**
* Parse the Uri (post-commit install session) or use the SessionInfo (pre-commit install
* session) to set up the installer for this install.
*
* @param source The source of package URI or SessionInfo
*
* @return {@code true} iff the installer could be set up
*/
private boolean processAppSnippet(@NonNull Object source) {
if (source instanceof Uri) {
return processPackageUri((Uri) source);
} else if (source instanceof SessionInfo) {
return processSessionInfo((SessionInfo) source);
}
return false;
}
@Override
public void onBackPressed() {
if (mSessionId != -1) {