Loading core/java/android/content/pm/IPackageInstaller.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -108,4 +108,6 @@ interface IPackageInstaller { @EnforcePermission("SET_DEVELOPER_VERIFICATION_USER_RESPONSE") DeveloperVerificationUserConfirmationInfo getDeveloperVerificationUserConfirmationInfo(int sessionId); void addDeveloperVerificationExperiment(String packageName, int verificationPolicy, in int[] results); } services/core/java/com/android/server/pm/PackageInstallerService.java +10 −0 Original line number Diff line number Diff line Loading @@ -2132,6 +2132,16 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements return verifierComponentName; } @Override public void addDeveloperVerificationExperiment(String packageName, int verificationPolicy, int[] results) { List<Integer> resultsList = new ArrayList<>(results.length); for (int i = 0; i < results.length; i++) { resultsList.add(results[i]); } mDeveloperVerifierController.addExperiment(packageName, verificationPolicy, resultsList); } void onUserAdded(int userId) { synchronized (mDeveloperVerificationPolicyPerUser) { mDeveloperVerificationPolicyPerUser.put(userId, DEFAULT_VERIFICATION_POLICY); Loading services/core/java/com/android/server/pm/PackageInstallerSession.java +16 −5 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import static android.content.pm.PackageManager.INSTALL_STAGED; import static android.content.pm.PackageManager.INSTALL_SUCCEEDED; import static android.content.pm.verify.developer.DeveloperVerificationSession.DEVELOPER_VERIFICATION_BYPASSED_REASON_ADB; import static android.content.pm.verify.developer.DeveloperVerificationSession.DEVELOPER_VERIFICATION_BYPASSED_REASON_EMERGENCY; import static android.content.pm.verify.developer.DeveloperVerificationSession.DEVELOPER_VERIFICATION_BYPASSED_REASON_TEST; import static android.content.pm.verify.developer.DeveloperVerificationSession.DEVELOPER_VERIFICATION_INCOMPLETE_NETWORK_UNAVAILABLE; import static android.os.Process.INVALID_UID; import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE; Loading Loading @@ -3032,18 +3033,28 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { onSessionVerificationFailure(e.error, errorMsg, /* extras= */ null); } if (shouldUseVerificationService()) { // Send the request to the verifier and wait for its response before the rest of // the installation can proceed. if (isMultiPackage()) { final String packageName = getPackageName(); if (mDeveloperVerifierController.hasExperiments(packageName)) { // This is a local testing environment. Use previously configured test results // instead of doing the real verification. mDeveloperVerifierController.startLocalExperiment( packageName, mDeveloperVerifierCallback); synchronized (mMetrics) { mMetrics.onDeveloperVerificationBypassed( DEVELOPER_VERIFICATION_BYPASSED_REASON_TEST); } } else if (isMultiPackage()) { // TODO(b/360129657) perform developer verification on each children session before // moving on to the next installation stage. resumeVerify(); } else { // Not a parent session // Send the request to the verifier and wait for its response before the rest of // the installation can proceed. final var infoPair = getSigningInfoAndDeclaredLibraries(); final SigningInfo signingInfo = infoPair.first; final List<SharedLibraryInfo> declaredLibraries = infoPair.second; if (!mDeveloperVerifierController.startVerificationSession( mPm::snapshotComputer, userId, sessionId, getPackageName(), mPm::snapshotComputer, userId, sessionId, packageName, Uri.fromFile(stageDir), signingInfo, declaredLibraries, mCurrentVerificationPolicy.get(), /* extensionParams= */ params.extensionParams, Loading Loading @@ -3274,7 +3285,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * Called by the session itself when the verifier cannot be connected because of infeasible * reasons such as it's not installed on the target user. */ private void onConnectionInfeasible() { public void onConnectionInfeasible() { mHandler.post(() -> { mDeveloperVerificationStatusInternal.setInternalStatus( DeveloperVerificationStatusInternal.STATUS_INFEASIBLE); Loading services/core/java/com/android/server/pm/PackageManagerShellCommand.java +49 −1 Original line number Diff line number Diff line Loading @@ -404,6 +404,8 @@ class PackageManagerShellCommand extends ShellCommand { return runGetDeveloperVerificationPolicy(); case "get-developer-verification-service-provider": return runGetDeveloperVerificationServiceProvider(); case "set-developer-verification-result": return runSetDeveloperVerificationResult(); default: { if (ART_SERVICE_COMMANDS.contains(cmd)) { return runArtServiceCommand(); Loading Loading @@ -4720,6 +4722,31 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } private int runSetDeveloperVerificationResult() { final PrintWriter pw = getOutPrintWriter(); try { final IPackageInstaller installer = mInterface.getPackageInstaller(); final String packageName = getNextArgRequired(); final int policy = Integer.parseInt(getNextArgRequired()); final int firstResult = Integer.parseInt(getNextArgRequired()); final List<Integer> results = new ArrayList<>(1); results.add(firstResult); String nextResult; while ((nextResult = getNextArg()) != null) { results.add(Integer.parseInt(nextResult)); } final int[] resultArray = new int[results.size()]; for (int i = 0; i < results.size(); i++) { resultArray[i] = results.get(i); } installer.addDeveloperVerificationExperiment(packageName, policy, resultArray); } catch (Exception e) { pw.println("Failure [" + e.getMessage() + "]"); return 1; } return 0; } @Override public void onHelp() { final PrintWriter pw = getOutPrintWriter(); Loading Loading @@ -5150,10 +5177,31 @@ 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(" get-developer-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(" get-developer-verification-service-provider"); pw.println(" Displays component name of developer verification service provider."); pw.println(" --user: show the policy of the given user (SYSTEM_USER if unspecified)"); pw.println(" set-developer-verification-result PACKAGE POLICY RESULT [RESULT...]"); pw.println(" Set the developer verification enforcement policy and the result(s)"); pw.println(" in sequence for the next N verification sessions for the given app where"); pw.println(" N equals to the number of specified result(s)."); pw.println(" The valid verification policy values are:"); pw.println(" 0 [none]: Do not block installs, regardless of verification result."); pw.println(" 1 [open]: Only block installs when verification fails."); pw.println(" 2 [warning]: The same as fail open."); pw.println(" 3 [closed]: Block installs when verification fails or cannot perform."); pw.println(" The valid verification result values are:"); pw.println(" 0 [invalid]: An invalid result value which will be skipped."); pw.println(" 1 [pass]: Verification passed."); pw.println(" 2 [reject]: Verification failed."); pw.println(" 3 [incomplete unknown]: Verification did not perform due to unknown."); pw.println(" 4 [incomplete network]: Verification did not perform due to network."); pw.println(" 5 [timeout]: Verification timed out."); pw.println(" 6 [disconnect]: Verification service disconnected."); pw.println(" 7 [infeasible]: Verification service was unavailable."); pw.println(""); pw.println(""); printArtServiceHelp(); Loading services/core/java/com/android/server/pm/verify/developer/DeveloperVerifierController.java +28 −0 Original line number Diff line number Diff line Loading @@ -141,6 +141,8 @@ public class DeveloperVerifierController { // Counter of active verification sessions per user; must be synced with the trackers map. private final SparseIntArray mSessionsCountPerUser = new SparseIntArray(); private final DeveloperVerifierExperimentProvider mExperimentProvider; /** * Get an instance of VerifierController. */ Loading @@ -162,6 +164,7 @@ public class DeveloperVerifierController { mHandler = handler; mDeveloperVerificationServiceProvider = developerVerificationServiceProvider; mInjector = injector; mExperimentProvider = new DeveloperVerifierExperimentProvider(mHandler); } /** Loading Loading @@ -682,6 +685,31 @@ public class DeveloperVerifierController { } } /** * Add an experiment to the experiment provider. * <p>Notice that invalid status codes will be ignored. Valid status codes are defined in * {@link DeveloperVerificationStatusInternal}. * </p> */ public void addExperiment(String packageName, int verificationPolicy, List<Integer> status) { mExperimentProvider.addExperiment(packageName, verificationPolicy, status); } /** * Check if there is an experiment for the given package. */ public boolean hasExperiments(String packageName) { return mExperimentProvider.hasExperiments(packageName); } /** * Start a local experiment for the given package. */ public void startLocalExperiment(String packageName, PackageInstallerSession.DeveloperVerifierCallback callback) { mExperimentProvider.runNextExperiment(packageName, callback); } private static class ServiceConnectorWrapper { // Remote service that receives verification requests private final @NonNull ServiceConnector<IDeveloperVerifierService> mRemoteService; Loading Loading
core/java/android/content/pm/IPackageInstaller.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -108,4 +108,6 @@ interface IPackageInstaller { @EnforcePermission("SET_DEVELOPER_VERIFICATION_USER_RESPONSE") DeveloperVerificationUserConfirmationInfo getDeveloperVerificationUserConfirmationInfo(int sessionId); void addDeveloperVerificationExperiment(String packageName, int verificationPolicy, in int[] results); }
services/core/java/com/android/server/pm/PackageInstallerService.java +10 −0 Original line number Diff line number Diff line Loading @@ -2132,6 +2132,16 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements return verifierComponentName; } @Override public void addDeveloperVerificationExperiment(String packageName, int verificationPolicy, int[] results) { List<Integer> resultsList = new ArrayList<>(results.length); for (int i = 0; i < results.length; i++) { resultsList.add(results[i]); } mDeveloperVerifierController.addExperiment(packageName, verificationPolicy, resultsList); } void onUserAdded(int userId) { synchronized (mDeveloperVerificationPolicyPerUser) { mDeveloperVerificationPolicyPerUser.put(userId, DEFAULT_VERIFICATION_POLICY); Loading
services/core/java/com/android/server/pm/PackageInstallerSession.java +16 −5 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import static android.content.pm.PackageManager.INSTALL_STAGED; import static android.content.pm.PackageManager.INSTALL_SUCCEEDED; import static android.content.pm.verify.developer.DeveloperVerificationSession.DEVELOPER_VERIFICATION_BYPASSED_REASON_ADB; import static android.content.pm.verify.developer.DeveloperVerificationSession.DEVELOPER_VERIFICATION_BYPASSED_REASON_EMERGENCY; import static android.content.pm.verify.developer.DeveloperVerificationSession.DEVELOPER_VERIFICATION_BYPASSED_REASON_TEST; import static android.content.pm.verify.developer.DeveloperVerificationSession.DEVELOPER_VERIFICATION_INCOMPLETE_NETWORK_UNAVAILABLE; import static android.os.Process.INVALID_UID; import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE; Loading Loading @@ -3032,18 +3033,28 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { onSessionVerificationFailure(e.error, errorMsg, /* extras= */ null); } if (shouldUseVerificationService()) { // Send the request to the verifier and wait for its response before the rest of // the installation can proceed. if (isMultiPackage()) { final String packageName = getPackageName(); if (mDeveloperVerifierController.hasExperiments(packageName)) { // This is a local testing environment. Use previously configured test results // instead of doing the real verification. mDeveloperVerifierController.startLocalExperiment( packageName, mDeveloperVerifierCallback); synchronized (mMetrics) { mMetrics.onDeveloperVerificationBypassed( DEVELOPER_VERIFICATION_BYPASSED_REASON_TEST); } } else if (isMultiPackage()) { // TODO(b/360129657) perform developer verification on each children session before // moving on to the next installation stage. resumeVerify(); } else { // Not a parent session // Send the request to the verifier and wait for its response before the rest of // the installation can proceed. final var infoPair = getSigningInfoAndDeclaredLibraries(); final SigningInfo signingInfo = infoPair.first; final List<SharedLibraryInfo> declaredLibraries = infoPair.second; if (!mDeveloperVerifierController.startVerificationSession( mPm::snapshotComputer, userId, sessionId, getPackageName(), mPm::snapshotComputer, userId, sessionId, packageName, Uri.fromFile(stageDir), signingInfo, declaredLibraries, mCurrentVerificationPolicy.get(), /* extensionParams= */ params.extensionParams, Loading Loading @@ -3274,7 +3285,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * Called by the session itself when the verifier cannot be connected because of infeasible * reasons such as it's not installed on the target user. */ private void onConnectionInfeasible() { public void onConnectionInfeasible() { mHandler.post(() -> { mDeveloperVerificationStatusInternal.setInternalStatus( DeveloperVerificationStatusInternal.STATUS_INFEASIBLE); Loading
services/core/java/com/android/server/pm/PackageManagerShellCommand.java +49 −1 Original line number Diff line number Diff line Loading @@ -404,6 +404,8 @@ class PackageManagerShellCommand extends ShellCommand { return runGetDeveloperVerificationPolicy(); case "get-developer-verification-service-provider": return runGetDeveloperVerificationServiceProvider(); case "set-developer-verification-result": return runSetDeveloperVerificationResult(); default: { if (ART_SERVICE_COMMANDS.contains(cmd)) { return runArtServiceCommand(); Loading Loading @@ -4720,6 +4722,31 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } private int runSetDeveloperVerificationResult() { final PrintWriter pw = getOutPrintWriter(); try { final IPackageInstaller installer = mInterface.getPackageInstaller(); final String packageName = getNextArgRequired(); final int policy = Integer.parseInt(getNextArgRequired()); final int firstResult = Integer.parseInt(getNextArgRequired()); final List<Integer> results = new ArrayList<>(1); results.add(firstResult); String nextResult; while ((nextResult = getNextArg()) != null) { results.add(Integer.parseInt(nextResult)); } final int[] resultArray = new int[results.size()]; for (int i = 0; i < results.size(); i++) { resultArray[i] = results.get(i); } installer.addDeveloperVerificationExperiment(packageName, policy, resultArray); } catch (Exception e) { pw.println("Failure [" + e.getMessage() + "]"); return 1; } return 0; } @Override public void onHelp() { final PrintWriter pw = getOutPrintWriter(); Loading Loading @@ -5150,10 +5177,31 @@ 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(" get-developer-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(" get-developer-verification-service-provider"); pw.println(" Displays component name of developer verification service provider."); pw.println(" --user: show the policy of the given user (SYSTEM_USER if unspecified)"); pw.println(" set-developer-verification-result PACKAGE POLICY RESULT [RESULT...]"); pw.println(" Set the developer verification enforcement policy and the result(s)"); pw.println(" in sequence for the next N verification sessions for the given app where"); pw.println(" N equals to the number of specified result(s)."); pw.println(" The valid verification policy values are:"); pw.println(" 0 [none]: Do not block installs, regardless of verification result."); pw.println(" 1 [open]: Only block installs when verification fails."); pw.println(" 2 [warning]: The same as fail open."); pw.println(" 3 [closed]: Block installs when verification fails or cannot perform."); pw.println(" The valid verification result values are:"); pw.println(" 0 [invalid]: An invalid result value which will be skipped."); pw.println(" 1 [pass]: Verification passed."); pw.println(" 2 [reject]: Verification failed."); pw.println(" 3 [incomplete unknown]: Verification did not perform due to unknown."); pw.println(" 4 [incomplete network]: Verification did not perform due to network."); pw.println(" 5 [timeout]: Verification timed out."); pw.println(" 6 [disconnect]: Verification service disconnected."); pw.println(" 7 [infeasible]: Verification service was unavailable."); pw.println(""); pw.println(""); printArtServiceHelp(); Loading
services/core/java/com/android/server/pm/verify/developer/DeveloperVerifierController.java +28 −0 Original line number Diff line number Diff line Loading @@ -141,6 +141,8 @@ public class DeveloperVerifierController { // Counter of active verification sessions per user; must be synced with the trackers map. private final SparseIntArray mSessionsCountPerUser = new SparseIntArray(); private final DeveloperVerifierExperimentProvider mExperimentProvider; /** * Get an instance of VerifierController. */ Loading @@ -162,6 +164,7 @@ public class DeveloperVerifierController { mHandler = handler; mDeveloperVerificationServiceProvider = developerVerificationServiceProvider; mInjector = injector; mExperimentProvider = new DeveloperVerifierExperimentProvider(mHandler); } /** Loading Loading @@ -682,6 +685,31 @@ public class DeveloperVerifierController { } } /** * Add an experiment to the experiment provider. * <p>Notice that invalid status codes will be ignored. Valid status codes are defined in * {@link DeveloperVerificationStatusInternal}. * </p> */ public void addExperiment(String packageName, int verificationPolicy, List<Integer> status) { mExperimentProvider.addExperiment(packageName, verificationPolicy, status); } /** * Check if there is an experiment for the given package. */ public boolean hasExperiments(String packageName) { return mExperimentProvider.hasExperiments(packageName); } /** * Start a local experiment for the given package. */ public void startLocalExperiment(String packageName, PackageInstallerSession.DeveloperVerifierCallback callback) { mExperimentProvider.runNextExperiment(packageName, callback); } private static class ServiceConnectorWrapper { // Remote service that receives verification requests private final @NonNull ServiceConnector<IDeveloperVerifierService> mRemoteService; Loading