summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/system-current.txt12
-rw-r--r--core/java/android/content/pm/IPackageInstaller.aidl4
-rw-r--r--core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl9
-rw-r--r--core/java/android/content/pm/verify/pkg/VerificationSession.java21
-rw-r--r--core/tests/coretests/src/android/content/pm/verify/VerificationSessionTest.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java23
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java92
-rw-r--r--services/core/java/com/android/server/pm/verify/pkg/VerifierController.java251
-rw-r--r--services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/verify/pkg/VerifierControllerTest.java6
10 files changed, 155 insertions, 277 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index decfc8cceeae..2b55d1671337 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -4705,7 +4705,7 @@ package android.content.pm.verify.pkg {
@FlaggedApi("android.content.pm.verification_service") public final class VerificationSession implements android.os.Parcelable {
method public int describeContents();
- method public long extendTimeRemaining(long);
+ method @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public long extendTimeRemaining(long);
method @NonNull public java.util.List<android.content.pm.SharedLibraryInfo> getDeclaredLibraries();
method @NonNull public android.os.PersistableBundle getExtensionParams();
method public int getId();
@@ -4713,12 +4713,12 @@ package android.content.pm.verify.pkg {
method @NonNull public String getPackageName();
method @NonNull public android.content.pm.SigningInfo getSigningInfo();
method @NonNull public android.net.Uri getStagedPackageUri();
- method public long getTimeoutTime();
+ method @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public long getTimeoutTime();
method public int getVerificationPolicy();
- method public void reportVerificationComplete(@NonNull android.content.pm.verify.pkg.VerificationStatus);
- method public void reportVerificationComplete(@NonNull android.content.pm.verify.pkg.VerificationStatus, @NonNull android.os.PersistableBundle);
- method public void reportVerificationIncomplete(int);
- method public boolean setVerificationPolicy(int);
+ method @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public void reportVerificationComplete(@NonNull android.content.pm.verify.pkg.VerificationStatus);
+ method @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public void reportVerificationComplete(@NonNull android.content.pm.verify.pkg.VerificationStatus, @NonNull android.os.PersistableBundle);
+ method @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public void reportVerificationIncomplete(int);
+ method @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public boolean setVerificationPolicy(int);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.verify.pkg.VerificationSession> CREATOR;
field public static final int VERIFICATION_INCOMPLETE_NETWORK_UNAVAILABLE = 1; // 0x1
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index ecea47944c72..c911326ccffd 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -94,9 +94,9 @@ interface IPackageInstaller {
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES,android.Manifest.permission.REQUEST_INSTALL_PACKAGES})")
void reportUnarchivalStatus(int unarchiveId, int status, long requiredStorageBytes, in PendingIntent userActionIntent, in UserHandle userHandle);
- @EnforcePermission("VERIFICATION_AGENT")
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
int getVerificationPolicy();
- @EnforcePermission("VERIFICATION_AGENT")
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
boolean setVerificationPolicy(int policy);
}
diff --git a/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl b/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl
index 2ab745205193..66caf2d0fec0 100644
--- a/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl
+++ b/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl
@@ -24,9 +24,16 @@ import android.os.PersistableBundle;
* @hide
*/
interface IVerificationSessionInterface {
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
long getTimeoutTime(int verificationId);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
long extendTimeRemaining(int verificationId, long additionalMs);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
boolean setVerificationPolicy(int verificationId, int policy);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
void reportVerificationIncomplete(int verificationId, int reason);
- void reportVerificationComplete(int verificationId, in VerificationStatus status, in @nullable PersistableBundle extensionResponse);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
+ void reportVerificationComplete(int verificationId, in VerificationStatus status);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)")
+ void reportVerificationCompleteWithExtensionResponse(int verificationId, in VerificationStatus status, in PersistableBundle response);
} \ No newline at end of file
diff --git a/core/java/android/content/pm/verify/pkg/VerificationSession.java b/core/java/android/content/pm/verify/pkg/VerificationSession.java
index 97f78e0978fa..4ade21198f37 100644
--- a/core/java/android/content/pm/verify/pkg/VerificationSession.java
+++ b/core/java/android/content/pm/verify/pkg/VerificationSession.java
@@ -19,6 +19,7 @@ package android.content.pm.verify.pkg;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.pm.Flags;
import android.content.pm.PackageInstaller;
@@ -165,8 +166,8 @@ public final class VerificationSession implements Parcelable {
/**
* Get the value of Clock.elapsedRealtime() at which time this verification
* will timeout as incomplete if no other verification response is provided.
- * @throws SecurityException if the caller is not the current verifier bound by the system.
*/
+ @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)
public long getTimeoutTime() {
try {
return mSession.getTimeoutTime(mId);
@@ -189,8 +190,8 @@ public final class VerificationSession implements Parcelable {
/**
* Override the verification policy for this session.
* @return True if the override was successful, False otherwise.
- * @throws SecurityException if the caller is not the current verifier bound by the system.
*/
+ @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)
public boolean setVerificationPolicy(@PackageInstaller.VerificationPolicy int policy) {
if (mVerificationPolicy == policy) {
// No effective policy change
@@ -214,8 +215,8 @@ public final class VerificationSession implements Parcelable {
* This may be called multiple times. If the request would bypass any max
* duration by the system, the method will return a lower value than the
* requested amount that indicates how much the time was extended.
- * @throws SecurityException if the caller is not the current verifier bound by the system.
*/
+ @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)
public long extendTimeRemaining(long additionalMs) {
try {
return mSession.extendTimeRemaining(mId, additionalMs);
@@ -226,9 +227,9 @@ public final class VerificationSession implements Parcelable {
/**
* Report to the system that verification could not be completed along
- * with an approximate reason to pass on to the installer.]
- * @throws SecurityException if the caller is not the current verifier bound by the system.
+ * with an approximate reason to pass on to the installer.
*/
+ @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)
public void reportVerificationIncomplete(@VerificationIncompleteReason int reason) {
try {
mSession.reportVerificationIncomplete(mId, reason);
@@ -241,11 +242,11 @@ public final class VerificationSession implements Parcelable {
* Report to the system that the verification has completed and the
* install process may act on that status to either block in the case
* of failure or continue to process the install in the case of success.
- * @throws SecurityException if the caller is not the current verifier bound by the system.
*/
+ @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)
public void reportVerificationComplete(@NonNull VerificationStatus status) {
try {
- mSession.reportVerificationComplete(mId, status, /* extensionResponse= */ null);
+ mSession.reportVerificationComplete(mId, status);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -255,12 +256,12 @@ public final class VerificationSession implements Parcelable {
* Same as {@link #reportVerificationComplete(VerificationStatus)}, but also provide
* a result to the extension params provided in the request, which will be passed to the
* installer in the installation result.
- * @throws SecurityException if the caller is not the current verifier bound by the system.
*/
+ @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)
public void reportVerificationComplete(@NonNull VerificationStatus status,
- @NonNull PersistableBundle extensionResponse) {
+ @NonNull PersistableBundle response) {
try {
- mSession.reportVerificationComplete(mId, status, extensionResponse);
+ mSession.reportVerificationCompleteWithExtensionResponse(mId, status, response);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/tests/coretests/src/android/content/pm/verify/VerificationSessionTest.java b/core/tests/coretests/src/android/content/pm/verify/VerificationSessionTest.java
index f1e1df5ae3fb..90ae306952fe 100644
--- a/core/tests/coretests/src/android/content/pm/verify/VerificationSessionTest.java
+++ b/core/tests/coretests/src/android/content/pm/verify/VerificationSessionTest.java
@@ -142,10 +142,10 @@ public class VerificationSessionTest {
new VerificationStatus.Builder().setVerified(true).build();
mTestSession.reportVerificationComplete(status);
verify(mTestSessionInterface, times(1)).reportVerificationComplete(
- eq(TEST_ID), eq(status), eq(null));
+ eq(TEST_ID), eq(status));
mTestSession.reportVerificationComplete(status, response);
verify(mTestSessionInterface, times(1))
- .reportVerificationComplete(
+ .reportVerificationCompleteWithExtensionResponse(
eq(TEST_ID), eq(status), eq(response));
final int reason = VerificationSession.VERIFICATION_INCOMPLETE_UNKNOWN;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 74167f686dea..2f2b45b8e8fb 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -39,7 +39,6 @@ import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.Manifest;
-import android.annotation.EnforcePermission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -88,7 +87,6 @@ import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelableException;
-import android.os.PermissionEnforcer;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteCallbackList;
@@ -317,8 +315,6 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
public PackageInstallerService(Context context, PackageManagerService pm,
Supplier<PackageParser2> apexParserSupplier) {
- super(PermissionEnforcer.fromContext(context));
-
mContext = context;
mPm = pm;
@@ -1886,20 +1882,23 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
@Override
- @EnforcePermission(android.Manifest.permission.VERIFICATION_AGENT)
public @PackageInstaller.VerificationPolicy int getVerificationPolicy() {
- getVerificationPolicy_enforcePermission();
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.VERIFICATION_AGENT)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("You need the "
+ + "com.android.permission.VERIFICATION_AGENT permission "
+ + "to get the verification policy");
+ }
return mVerificationPolicy.get();
}
@Override
- @EnforcePermission(android.Manifest.permission.VERIFICATION_AGENT)
public boolean setVerificationPolicy(@PackageInstaller.VerificationPolicy int policy) {
- setVerificationPolicy_enforcePermission();
- final int callingUid = getCallingUid();
- // Only the verifier currently bound by the system can change the policy, except for Shell
- if (!PackageManagerServiceUtils.isRootOrShell(callingUid)) {
- mVerifierController.assertCallerIsCurrentVerifier(callingUid);
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.VERIFICATION_AGENT)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("You need the "
+ + "com.android.permission.VERIFICATION_AGENT permission "
+ + "to set the verification policy");
}
if (!isValidVerificationPolicy(policy)) {
return false;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index d417505f46e7..e7930890d0fe 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -2897,13 +2897,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
// Send the request to the verifier and wait for its response before the rest of
// the installation can proceed.
- final VerifierCallback verifierCallback = new VerifierCallback();
if (!mVerifierController.startVerificationSession(mPm::snapshotComputer, userId,
sessionId, getPackageName(), Uri.fromFile(stageDir), signingInfo,
declaredLibraries, mVerificationPolicy.get(), /* extensionParams= */ null,
- verifierCallback, /* retry= */ false)) {
- // A verifier is installed but cannot be connected.
- verifierCallback.onConnectionFailed();
+ new VerifierCallback(), /* retry= */ false)) {
+ // A verifier is installed but cannot be connected. Installation disallowed.
+ onSessionVerificationFailure(INSTALL_FAILED_INTERNAL_ERROR,
+ "A verifier agent is available on device but cannot be connected.",
+ /* extras= */ null);
}
} else {
// No need to check with verifier. Proceed with the rest of the verification.
@@ -3007,6 +3008,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
onSessionVerificationFailure(INSTALL_FAILED_VERIFICATION_FAILURE,
"A verifier agent is available on device but cannot be connected.",
bundle);
+
});
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 34005b37d1a1..e66ae21c4778 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -399,10 +399,6 @@ class PackageManagerShellCommand extends ShellCommand {
return runUnarchive();
case "get-domain-verification-agent":
return runGetDomainVerificationAgent();
- case "get-verification-policy":
- return runGetVerificationPolicy();
- case "set-verification-policy":
- return runSetVerificationPolicy();
default: {
if (ART_SERVICE_COMMANDS.contains(cmd)) {
return runArtServiceCommand();
@@ -4656,86 +4652,6 @@ class PackageManagerShellCommand extends ShellCommand {
return 0;
}
- private int runGetVerificationPolicy() throws RemoteException {
- final PrintWriter pw = getOutPrintWriter();
- int userId = UserHandle.USER_ALL;
-
- String opt;
- while ((opt = getNextOption()) != null) {
- if (opt.equals("--user")) {
- userId = UserHandle.parseUserArg(getNextArgRequired());
- if (userId != UserHandle.USER_ALL && userId != UserHandle.USER_CURRENT) {
- UserManagerInternal umi =
- LocalServices.getService(UserManagerInternal.class);
- UserInfo userInfo = umi.getUserInfo(userId);
- if (userInfo == null) {
- pw.println("Failure [user " + userId + " doesn't exist]");
- return 1;
- }
- }
- } else {
- pw.println("Error: Unknown option: " + opt);
- return 1;
- }
- }
- final int translatedUserId =
- translateUserId(userId, UserHandle.USER_SYSTEM, "runGetVerificationPolicy");
- try {
- final IPackageInstaller installer = mInterface.getPackageInstaller();
- // TODO(b/360129657): global verification policy should be per user
- final int policy = installer.getVerificationPolicy();
- pw.println(policy);
- } catch (Exception e) {
- pw.println("Failure [" + e.getMessage() + "]");
- return 1;
- }
- return 0;
- }
-
- private int runSetVerificationPolicy() throws RemoteException {
- final PrintWriter pw = getOutPrintWriter();
- int userId = UserHandle.USER_ALL;
-
- String opt;
- while ((opt = getNextOption()) != null) {
- if (opt.equals("--user")) {
- userId = UserHandle.parseUserArg(getNextArgRequired());
- if (userId != UserHandle.USER_ALL && userId != UserHandle.USER_CURRENT) {
- UserManagerInternal umi =
- LocalServices.getService(UserManagerInternal.class);
- UserInfo userInfo = umi.getUserInfo(userId);
- if (userInfo == null) {
- pw.println("Failure [user " + userId + " doesn't exist]");
- return 1;
- }
- }
- } else {
- pw.println("Error: Unknown option: " + opt);
- return 1;
- }
- }
- final String policyStr = getNextArg();
- if (policyStr == null) {
- pw.println("Error: policy not specified");
- return 1;
- }
- final int translatedUserId =
- translateUserId(userId, UserHandle.USER_SYSTEM, "runSetVerificationPolicy");
- try {
- final IPackageInstaller installer = mInterface.getPackageInstaller();
- // TODO(b/360129657): global verification policy should be per user
- final boolean success = installer.setVerificationPolicy(Integer.parseInt(policyStr));
- if (!success) {
- pw.println("Failure setting verification policy.");
- return 1;
- }
- } catch (Exception e) {
- pw.println("Failure [" + e.getMessage() + "]");
- return 1;
- }
- return 0;
- }
-
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
@@ -5168,14 +5084,6 @@ class PackageManagerShellCommand extends ShellCommand {
pw.println(" --user: return the agent of the given user (SYSTEM_USER if unspecified)");
pw.println(" get-package-storage-stats [--user <USER_ID>] <PACKAGE>");
pw.println(" Return the storage stats for the given app, if present");
- pw.println(" get-verification-policy [--user USER_ID]");
- pw.println(" Display current verification enforcement policy which will be applied to");
- pw.println(" all the future installation sessions");
- pw.println(" --user: show the policy of the given user (SYSTEM_USER if unspecified)");
- pw.println(" set-verification-policy POLICY [--user USER_ID]");
- pw.println(" Sets the verification policy of all the future installation sessions.");
- pw.println(" --user: set the policy of the given user (SYSTEM_USER if unspecified)");
- pw.println("");
pw.println("");
printArtServiceHelp();
pw.println("");
diff --git a/services/core/java/com/android/server/pm/verify/pkg/VerifierController.java b/services/core/java/com/android/server/pm/verify/pkg/VerifierController.java
index 78849d286ebe..a35618b309bb 100644
--- a/services/core/java/com/android/server/pm/verify/pkg/VerifierController.java
+++ b/services/core/java/com/android/server/pm/verify/pkg/VerifierController.java
@@ -18,12 +18,13 @@ package com.android.server.pm.verify.pkg;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
-import static android.os.Process.INVALID_UID;
import static android.os.Process.SYSTEM_UID;
import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
@@ -113,17 +114,10 @@ public class VerifierController {
private final Context mContext;
private final Handler mHandler;
- // Guards the remote service object, as well as the verifier name and UID, which should all be
- // changed at the same time.
- private final Object mLock = new Object();
@Nullable
- @GuardedBy("mLock")
private ServiceConnector<IVerifierService> mRemoteService;
@Nullable
- @GuardedBy("mLock")
private ComponentName mRemoteServiceComponentName;
- @GuardedBy("mLock")
- private int mRemoteServiceUid = INVALID_UID;
@NonNull
private Injector mInjector;
@@ -149,11 +143,9 @@ public class VerifierController {
*/
@Nullable
public String getVerifierPackageName(Supplier<Computer> snapshotSupplier, int userId) {
- synchronized (mLock) {
- if (isVerifierConnectedLocked()) {
- // Verifier is connected or is being connected, so it must be installed.
- return mRemoteServiceComponentName.getPackageName();
- }
+ if (isVerifierConnected()) {
+ // Verifier is connected or is being connected, so it must be installed.
+ return mRemoteServiceComponentName.getPackageName();
}
// Verifier has been disconnected, or it hasn't been connected. Check if it's installed.
return mInjector.getVerifierPackageName(snapshotSupplier.get(), userId);
@@ -186,29 +178,16 @@ public class VerifierController {
}
return true;
}
- Computer snapshot = snapshotSupplier.get();
Pair<ServiceConnector<IVerifierService>, ComponentName> result =
- mInjector.getRemoteService(snapshot, mContext, userId, mHandler);
+ mInjector.getRemoteService(snapshotSupplier.get(), mContext, userId, mHandler);
if (result == null || result.first == null) {
if (DEBUG) {
Slog.i(TAG, "Unable to find a qualified verifier.");
}
return false;
}
- final int verifierUid = snapshot.getPackageUidInternal(
- result.second.getPackageName(), 0, userId, /* callingUid= */ SYSTEM_UID);
- if (verifierUid == INVALID_UID) {
- if (DEBUG) {
- Slog.i(TAG, "Unable to find the UID of the qualified verifier.");
- }
- return false;
- }
- synchronized (mLock) {
- mRemoteService = result.first;
- mRemoteServiceComponentName = result.second;
- mRemoteServiceUid = verifierUid;
- }
-
+ mRemoteService = result.first;
+ mRemoteServiceComponentName = result.second;
if (DEBUG) {
Slog.i(TAG, "Connecting to a qualified verifier: " + mRemoteServiceComponentName);
}
@@ -233,13 +212,10 @@ public class VerifierController {
}
private void destroy() {
- synchronized (mLock) {
- if (isVerifierConnectedLocked()) {
- mRemoteService.unbind();
- mRemoteService = null;
- mRemoteServiceComponentName = null;
- mRemoteServiceUid = INVALID_UID;
- }
+ if (isVerifierConnected()) {
+ mRemoteService.unbind();
+ mRemoteService = null;
+ mRemoteServiceComponentName = null;
}
}
});
@@ -247,8 +223,7 @@ public class VerifierController {
return true;
}
- @GuardedBy("mLock")
- private boolean isVerifierConnectedLocked() {
+ private boolean isVerifierConnected() {
return mRemoteService != null && mRemoteServiceComponentName != null;
}
@@ -257,21 +232,19 @@ public class VerifierController {
* requested for verification.
*/
public void notifyPackageNameAvailable(@NonNull String packageName) {
- synchronized (mLock) {
- if (!isVerifierConnectedLocked()) {
- if (DEBUG) {
- Slog.i(TAG, "Verifier is not connected. Not notifying package name available");
- }
- return;
+ if (!isVerifierConnected()) {
+ if (DEBUG) {
+ Slog.i(TAG, "Verifier is not connected. Not notifying package name available");
}
- // Best effort. We don't check for the result.
- mRemoteService.run(service -> {
- if (DEBUG) {
- Slog.i(TAG, "Notifying package name available for " + packageName);
- }
- service.onPackageNameAvailable(packageName);
- });
+ return;
}
+ // Best effort. We don't check for the result.
+ mRemoteService.run(service -> {
+ if (DEBUG) {
+ Slog.i(TAG, "Notifying package name available for " + packageName);
+ }
+ service.onPackageNameAvailable(packageName);
+ });
}
/**
@@ -280,29 +253,27 @@ public class VerifierController {
* will no longer be requested for verification, possibly because the installation is canceled.
*/
public void notifyVerificationCancelled(@NonNull String packageName) {
- synchronized (mLock) {
- if (!isVerifierConnectedLocked()) {
- if (DEBUG) {
- Slog.i(TAG, "Verifier is not connected. Not notifying verification cancelled");
- }
- return;
+ if (!isVerifierConnected()) {
+ if (DEBUG) {
+ Slog.i(TAG, "Verifier is not connected. Not notifying verification cancelled");
}
- // Best effort. We don't check for the result.
- mRemoteService.run(service -> {
- if (DEBUG) {
- Slog.i(TAG, "Notifying verification cancelled for " + packageName);
- }
- service.onVerificationCancelled(packageName);
- });
+ return;
}
+ // Best effort. We don't check for the result.
+ mRemoteService.run(service -> {
+ if (DEBUG) {
+ Slog.i(TAG, "Notifying verification cancelled for " + packageName);
+ }
+ service.onVerificationCancelled(packageName);
+ });
}
/**
* Called to notify the bound verifier agent that a package that's pending installation needs
* to be verified right now.
* <p>The verification request must be sent to the verifier as soon as the verifier is
- * connected. If the connection cannot be made within the specified time limit from
- * when the request is sent out, we consider the verification to be failed and notify the
+ * connected. If the connection cannot be made within {@link #CONNECTION_TIMEOUT_SECONDS}</p>
+ * of when the request is sent out, we consider the verification to be failed and notify the
* installation session.</p>
* <p>If a response is not returned from the verifier agent within a timeout duration from the
* time the request is sent to the verifier, the verification will be considered a failure.</p>
@@ -320,48 +291,43 @@ public class VerifierController {
if (!bindToVerifierServiceIfNeeded(snapshotSupplier, userId)) {
return false;
}
+ if (!isVerifierConnected()) {
+ if (DEBUG) {
+ Slog.i(TAG, "Verifier is not connected. Not notifying verification required");
+ }
+ // Normally this should not happen because we just tried to bind. But if the verifier
+ // just crashed or just became unavailable, we should notify the installation session so
+ // it can finish with a verification failure.
+ return false;
+ }
// For now, the verification id is the same as the installation session id.
final int verificationId = installationSessionId;
- synchronized (mLock) {
- if (!isVerifierConnectedLocked()) {
+ final VerificationSession session = new VerificationSession(
+ /* id= */ verificationId,
+ /* installSessionId= */ installationSessionId,
+ packageName, stagedPackageUri, signingInfo, declaredLibraries, extensionParams,
+ verificationPolicy, new VerificationSessionInterface(callback));
+ AndroidFuture<Void> unusedFuture = mRemoteService.post(service -> {
+ if (!retry) {
if (DEBUG) {
- Slog.i(TAG, "Verifier is not connected. Not notifying verification required");
+ Slog.i(TAG, "Notifying verification required for session " + verificationId);
}
- // Normally this should not happen because we just tried to bind. But if the
- // verifier just crashed or just became unavailable, we should notify the
- // installation session so it can finish with a verification failure.
- return false;
- }
- final VerificationSession session = new VerificationSession(
- /* id= */ verificationId,
- /* installSessionId= */ installationSessionId,
- packageName, stagedPackageUri, signingInfo, declaredLibraries, extensionParams,
- verificationPolicy, new VerificationSessionInterface(callback));
- AndroidFuture<Void> unusedFuture = mRemoteService.post(service -> {
- if (!retry) {
- if (DEBUG) {
- Slog.i(TAG, "Notifying verification required for session "
- + verificationId);
- }
- service.onVerificationRequired(session);
- } else {
- if (DEBUG) {
- Slog.i(TAG, "Notifying verification retry for session "
- + verificationId);
- }
- service.onVerificationRetry(session);
+ service.onVerificationRequired(session);
+ } else {
+ if (DEBUG) {
+ Slog.i(TAG, "Notifying verification retry for session " + verificationId);
}
- }).orTimeout(mInjector.getVerifierConnectionTimeoutMillis(), TimeUnit.MILLISECONDS)
- .whenComplete((res, err) -> {
- if (err != null) {
- Slog.e(TAG, "Error notifying verification request for session "
- + verificationId, err);
- // Notify the installation session so it can finish with verification
- // failure.
- callback.onConnectionFailed();
- }
- });
- }
+ service.onVerificationRetry(session);
+ }
+ }).orTimeout(mInjector.getVerifierConnectionTimeoutMillis(), TimeUnit.MILLISECONDS)
+ .whenComplete((res, err) -> {
+ if (err != null) {
+ Slog.e(TAG, "Error notifying verification request for session " + verificationId,
+ err);
+ // Notify the installation session so it can finish with verification failure.
+ callback.onConnectionFailed();
+ }
+ });
// Keep track of the session status with the ID. Start counting down the session timeout.
final long defaultTimeoutMillis = mInjector.getVerificationRequestTimeoutMillis();
final long maxExtendedTimeoutMillis = mInjector.getMaxVerificationExtendedTimeoutMillis();
@@ -403,27 +369,24 @@ public class VerifierController {
* Called to notify the bound verifier agent that a verification request has timed out.
*/
public void notifyVerificationTimeout(int verificationId) {
- synchronized (mLock) {
- if (!isVerifierConnectedLocked()) {
- if (DEBUG) {
- Slog.i(TAG,
- "Verifier is not connected. Not notifying timeout for "
- + verificationId);
- }
- return;
+ if (!isVerifierConnected()) {
+ if (DEBUG) {
+ Slog.i(TAG,
+ "Verifier is not connected. Not notifying timeout for " + verificationId);
}
- AndroidFuture<Void> unusedFuture = mRemoteService.post(service -> {
- if (DEBUG) {
- Slog.i(TAG, "Notifying timeout for " + verificationId);
- }
- service.onVerificationTimeout(verificationId);
- }).whenComplete((res, err) -> {
- if (err != null) {
- Slog.e(TAG, "Error notifying VerificationTimeout for session "
- + verificationId, err);
- }
- });
+ return;
}
+ AndroidFuture<Void> unusedFuture = mRemoteService.post(service -> {
+ if (DEBUG) {
+ Slog.i(TAG, "Notifying timeout for " + verificationId);
+ }
+ service.onVerificationTimeout(verificationId);
+ }).whenComplete((res, err) -> {
+ if (err != null) {
+ Slog.e(TAG, "Error notifying VerificationTimeout for session "
+ + verificationId, (Throwable) err);
+ }
+ });
}
/**
@@ -442,19 +405,17 @@ public class VerifierController {
}
}
- /**
- * Assert that the calling UID is the same as the UID of the currently connected verifier.
- */
- public void assertCallerIsCurrentVerifier(int callingUid) {
- synchronized (mLock) {
- if (!isVerifierConnectedLocked()) {
- throw new IllegalStateException(
- "Unable to proceed because the verifier has been disconnected.");
- }
- if (callingUid != mRemoteServiceUid) {
- throw new IllegalStateException(
- "Calling uid " + callingUid + " is not the current verifier.");
- }
+ @RequiresPermission(Manifest.permission.VERIFICATION_AGENT)
+ private void checkCallerPermission() {
+ // TODO: think of a better way to test it on non-eng builds
+ if (Build.IS_ENG) {
+ return;
+ }
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.VERIFICATION_AGENT)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("You need the"
+ + " com.android.permission.VERIFICATION_AGENT permission"
+ + " to use VerificationSession APIs.");
}
}
@@ -468,7 +429,7 @@ public class VerifierController {
@Override
public long getTimeoutTime(int verificationId) {
- assertCallerIsCurrentVerifier(getCallingUid());
+ checkCallerPermission();
synchronized (mVerificationStatus) {
final VerificationStatusTracker tracker = mVerificationStatus.get(verificationId);
if (tracker == null) {
@@ -481,7 +442,7 @@ public class VerifierController {
@Override
public long extendTimeRemaining(int verificationId, long additionalMs) {
- assertCallerIsCurrentVerifier(getCallingUid());
+ checkCallerPermission();
synchronized (mVerificationStatus) {
final VerificationStatusTracker tracker = mVerificationStatus.get(verificationId);
if (tracker == null) {
@@ -495,7 +456,7 @@ public class VerifierController {
@Override
public boolean setVerificationPolicy(int verificationId,
@PackageInstaller.VerificationPolicy int policy) {
- assertCallerIsCurrentVerifier(getCallingUid());
+ checkCallerPermission();
synchronized (mVerificationStatus) {
final VerificationStatusTracker tracker = mVerificationStatus.get(verificationId);
if (tracker == null) {
@@ -508,7 +469,7 @@ public class VerifierController {
@Override
public void reportVerificationIncomplete(int id, int reason) {
- assertCallerIsCurrentVerifier(getCallingUid());
+ checkCallerPermission();
final VerificationStatusTracker tracker;
synchronized (mVerificationStatus) {
tracker = mVerificationStatus.get(id);
@@ -523,9 +484,15 @@ public class VerifierController {
}
@Override
- public void reportVerificationComplete(int id, VerificationStatus verificationStatus,
- @Nullable PersistableBundle extensionResponse) {
- assertCallerIsCurrentVerifier(getCallingUid());
+ public void reportVerificationComplete(int id, VerificationStatus verificationStatus) {
+ reportVerificationCompleteWithExtensionResponse(id, verificationStatus,
+ /* extensionResponse= */ null);
+ }
+
+ @Override
+ public void reportVerificationCompleteWithExtensionResponse(int id,
+ VerificationStatus verificationStatus, PersistableBundle extensionResponse) {
+ checkCallerPermission();
final VerificationStatusTracker tracker;
synchronized (mVerificationStatus) {
tracker = mVerificationStatus.get(id);
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/verify/pkg/VerifierControllerTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/verify/pkg/VerifierControllerTest.java
index 3046d4beb7a3..24617984eaf7 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/verify/pkg/VerifierControllerTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/verify/pkg/VerifierControllerTest.java
@@ -24,7 +24,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -50,7 +49,6 @@ import android.util.Pair;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.infra.ServiceConnector;
@@ -124,10 +122,6 @@ public class VerifierControllerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- // Mock that the UID of this test becomes the UID of the verifier
- when(mSnapshot.getPackageUidInternal(anyString(), anyLong(), anyInt(), anyInt()))
- .thenReturn(InstrumentationRegistry.getInstrumentation().getContext()
- .getApplicationInfo().uid);
when(mInjector.getVerifierPackageName(any(Computer.class), anyInt())).thenReturn(
TEST_VERIFIER_COMPONENT_NAME.getPackageName());
when(mInjector.getRemoteService(