From 3752c462ef04dbb6fad36e2b97571e263143d7ea Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Thu, 9 Aug 2018 16:23:22 +0200 Subject: [PATCH 1/3] Fix BackgroundDexOptServiceIntegrationTests - Ensure that calling uid is shell. - Clear calling identity such that we don't get permission failures when calling getCurrentUser() Test: self Exempt-From-Owner-Approval: cherry-pick Merged-In: Ifbaceb47edbbc4a6b002d49411ca4635ffc33a08 Change-Id: Ifbaceb47edbbc4a6b002d49411ca4635ffc33a08 Fixes: 111798412 --- .../server/pm/PackageManagerService.java | 22 ++++++++++++- ...ckgroundDexOptServiceIntegrationTests.java | 33 ++++++++----------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index f938b65b48c31..9e6590e747ccb 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -9004,6 +9004,20 @@ public class PackageManagerService extends IPackageManager.Stub } } + /** + * Enforces that only the system UID or shell's UID can call a method exposed + * via Binder. + * + * @param message used as message if SecurityException is thrown + * @throws SecurityException if the caller is not system or shell + */ + private static void enforceSystemOrShell(String message) { + final int uid = Binder.getCallingUid(); + if (uid != Process.SYSTEM_UID && uid != Process.SHELL_UID) { + throw new SecurityException(message); + } + } + @Override public void performFstrimIfNeeded() { enforceSystemOrRoot("Only the system can request fstrim"); @@ -9498,7 +9512,13 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(Binder.getCallingUid()) != null) { return false; } - return BackgroundDexOptService.runIdleOptimizationsNow(this, mContext, packageNames); + enforceSystemOrShell("runBackgroundDexoptJob"); + final long identity = Binder.clearCallingIdentity(); + try { + return BackgroundDexOptService.runIdleOptimizationsNow(this, mContext, packageNames); + } finally { + Binder.restoreCallingIdentity(identity); + } } private static List findSharedLibraries(PackageParser.Package p) { diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java index e247951f16ef0..e509d2d87bf7d 100644 --- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java +++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java @@ -17,8 +17,10 @@ package com.android.server.pm; import android.app.AlarmManager; +import android.app.UiAutomation; import android.content.Context; import android.os.Environment; +import android.os.ParcelFileDescriptor; import android.os.SystemProperties; import android.os.storage.StorageManager; import android.support.test.InstrumentationRegistry; @@ -34,6 +36,7 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -141,27 +144,17 @@ public final class BackgroundDexOptServiceIntegrationTests { // Run the command and return the stdout. private static String runShellCommand(String cmd) throws IOException { Log.i(TAG, String.format("running command: '%s'", cmd)); - long startTime = System.nanoTime(); - Process p = Runtime.getRuntime().exec(cmd); - int res; - try { - res = p.waitFor(); - } catch (InterruptedException e) { - throw new RuntimeException(e); + ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation() + .executeShellCommand(cmd); + byte[] buf = new byte[512]; + int bytesRead; + FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); + StringBuilder stdout = new StringBuilder(); + while ((bytesRead = fis.read(buf)) != -1) { + stdout.append(new String(buf, 0, bytesRead)); } - String stdout = inputStreamToString(p.getInputStream()); - String stderr = inputStreamToString(p.getErrorStream()); - long elapsedTime = System.nanoTime() - startTime; - Log.i(TAG, String.format("ran command: '%s' in %d ms with return code %d", cmd, - TimeUnit.NANOSECONDS.toMillis(elapsedTime), res)); - Log.i(TAG, "stdout"); - Log.i(TAG, stdout); - Log.i(TAG, "stderr"); - Log.i(TAG, stderr); - if (res != 0) { - throw new RuntimeException(String.format("failed command: '%s'", cmd)); - } - return stdout; + fis.close(); + return stdout.toString(); } // Run the command and return the stdout split by lines. From a8ff8b252962337085b14fcb2553dc1f25f4d73b Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Fri, 31 Aug 2018 15:47:01 -0700 Subject: [PATCH 2/3] Framework: Allow root to send bg-dexopt To allow testing, and work on rooted userdebug devices, allow the root user to issue package bg-dexopt commands. Bug: 111798412 Exempt-From-Owner-Approval: cherry-pick Test: atest BackgroundDexOptServiceIntegrationTests Merged-In: I5f52b8322ba386c797a9176a1b216cc547c66456 Change-Id: I5f52b8322ba386c797a9176a1b216cc547c66456 --- .../com/android/server/pm/PackageManagerService.java | 10 +++++----- .../android/server/pm/PackageManagerShellCommand.java | 1 + .../pm/BackgroundDexOptServiceIntegrationTests.java | 7 ++++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 9e6590e747ccb..aac8dad52dd73 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -9005,15 +9005,15 @@ public class PackageManagerService extends IPackageManager.Stub } /** - * Enforces that only the system UID or shell's UID can call a method exposed - * via Binder. + * Enforces that only the system UID or root's UID or shell's UID can call + * a method exposed via Binder. * * @param message used as message if SecurityException is thrown * @throws SecurityException if the caller is not system or shell */ - private static void enforceSystemOrShell(String message) { + private static void enforceSystemOrRootOrShell(String message) { final int uid = Binder.getCallingUid(); - if (uid != Process.SYSTEM_UID && uid != Process.SHELL_UID) { + if (uid != Process.SYSTEM_UID && uid != Process.ROOT_UID && uid != Process.SHELL_UID) { throw new SecurityException(message); } } @@ -9512,7 +9512,7 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(Binder.getCallingUid()) != null) { return false; } - enforceSystemOrShell("runBackgroundDexoptJob"); + enforceSystemOrRootOrShell("runBackgroundDexoptJob"); final long identity = Binder.clearCallingIdentity(); try { return BackgroundDexOptService.runIdleOptimizationsNow(this, mContext, packageNames); diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index e1c13026507fb..242f9c302f5e7 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -1334,6 +1334,7 @@ class PackageManagerShellCommand extends ShellCommand { } boolean result = mInterface.runBackgroundDexoptJob(packageNames.isEmpty() ? null : packageNames); + getOutPrintWriter().println(result ? "Success" : "Failure"); return result ? 0 : -1; } diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java index e509d2d87bf7d..fd20f4a1fa77d 100644 --- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java +++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java @@ -154,6 +154,8 @@ public final class BackgroundDexOptServiceIntegrationTests { stdout.append(new String(buf, 0, bytesRead)); } fis.close(); + Log.i(TAG, "stdout"); + Log.i(TAG, stdout.toString()); return stdout.toString(); } @@ -202,7 +204,10 @@ public final class BackgroundDexOptServiceIntegrationTests { // TODO(aeubanks): figure out how to get scheduled bg-dexopt to run private static void runBackgroundDexOpt() throws IOException { - runShellCommand("cmd package bg-dexopt-job " + PACKAGE_NAME); + String result = runShellCommand("cmd package bg-dexopt-job " + PACKAGE_NAME); + if (!result.trim().equals("Success")) { + throw new IllegalStateException("Expected command success, received >" + result + "<"); + } } // Set the time ahead of the last use time of the test app in days. From 3bc264d1a0fb82f54c989ca7724306e5c2d57f4c Mon Sep 17 00:00:00 2001 From: Brett Chabot Date: Fri, 1 Mar 2019 14:43:20 -0800 Subject: [PATCH 3/3] Migrate BackgroundDexOptServiceIntegrationTests to androidx.test See go/jetpack-test-android-migration Partial cherry-pick of commit a86ec10b96244a32931cd2949be0f55ee3ea14c8. Test: atest BackgroundDexOptServiceIntegrationTests Change-Id: I15d10a1962210cde7e079590437009f6a5938db2 Merged-In: I32fe3297656eec6060da6c7e24582bcd5315fb16 --- tests/BackgroundDexOptServiceIntegrationTests/Android.bp | 2 +- .../AndroidManifest.xml | 2 +- .../BackgroundDexOptServiceIntegrationTests/AndroidTest.xml | 2 +- .../server/pm/BackgroundDexOptServiceIntegrationTests.java | 5 ++--- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/BackgroundDexOptServiceIntegrationTests/Android.bp b/tests/BackgroundDexOptServiceIntegrationTests/Android.bp index 036f845268894..a85d129b013aa 100644 --- a/tests/BackgroundDexOptServiceIntegrationTests/Android.bp +++ b/tests/BackgroundDexOptServiceIntegrationTests/Android.bp @@ -17,7 +17,7 @@ android_test { name: "BackgroundDexOptServiceIntegrationTests", srcs: ["src/**/*.java"], - static_libs: ["android-support-test"], + static_libs: ["androidx.test.rules"], platform_apis: true, test_suites: ["device-tests"], certificate: "platform", diff --git a/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml index afae155f88fea..aec9f77cf922b 100644 --- a/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml +++ b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml @@ -34,7 +34,7 @@ diff --git a/tests/BackgroundDexOptServiceIntegrationTests/AndroidTest.xml b/tests/BackgroundDexOptServiceIntegrationTests/AndroidTest.xml index 9bb1e280b861f..a532422a38d37 100644 --- a/tests/BackgroundDexOptServiceIntegrationTests/AndroidTest.xml +++ b/tests/BackgroundDexOptServiceIntegrationTests/AndroidTest.xml @@ -50,6 +50,6 @@