diff options
10 files changed, 109 insertions, 11 deletions
diff --git a/core/jni/core_jni_helpers.h b/core/jni/core_jni_helpers.h index eeda275b811c..ad8aeb20ab3e 100644 --- a/core/jni/core_jni_helpers.h +++ b/core/jni/core_jni_helpers.h @@ -90,6 +90,12 @@ static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className, return res; } +static inline jobject jniGetReferent(JNIEnv* env, jobject ref) { + jclass cls = FindClassOrDie(env, "java/lang/ref/Reference"); + jmethodID get = GetMethodIDOrDie(env, cls, "get", "()Ljava/lang/Object;"); + return env->CallObjectMethod(ref, get); +} + /** * Read the specified field from jobject, and convert to std::string. * If the field cannot be obtained, return defaultValue. diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index f6c2ee264cb5..02815a571db8 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -503,14 +503,14 @@ public class BugreportProgressService extends Service { } if (msg.what != MSG_SERVICE_COMMAND) { - // Sanity check. + // Confidence check. Log.e(TAG, "Invalid message type: " + msg.what); return; } // At this point it's handling onStartCommand(), with the intent passed as an Extra. if (!(msg.obj instanceof Intent)) { - // Sanity check. + // Confidence check. Log.wtf(TAG, "handleMessage(): invalid msg.obj type: " + msg.obj); return; } diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java index b95092a9384c..b8cfa1e80043 100644 --- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java +++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java @@ -561,7 +561,7 @@ public class BugreportReceiverTest { // Clear properties mContext.getSharedPreferences(PREFS_BUGREPORT, Context.MODE_PRIVATE) .edit().clear().commit(); - // Sanity check... + // Confidence check... assertEquals("Did not reset properties", STATE_UNKNOWN, getWarningState(mContext, STATE_UNKNOWN)); } else { diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java index 7dd5290ee83b..64d5025807e7 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -2104,7 +2104,7 @@ public class Tethering { } private boolean hasCallingPermission(@NonNull String permission) { - return mContext.checkCallingPermission(permission) == PERMISSION_GRANTED; + return mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED; } /** Unregister tethering event callback */ diff --git a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java index 64be2d9a5599..d206ea0b4d45 100644 --- a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java +++ b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java @@ -553,7 +553,6 @@ public class EthernetTetheringTest { TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class); TestNetworkInterface iface = tnm.createTapInterface(); Log.d(TAG, "Created test interface " + iface.getInterfaceName()); - assertNotNull(NetworkInterface.getByName(iface.getInterfaceName())); return iface; } diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index e12cb8f533a7..f116a24a76e1 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -352,6 +352,11 @@ public abstract class ApexManager { public abstract boolean destroyCeSnapshotsNotSpecified(int userId, int[] retainRollbackIds); /** + * Inform apexd that the boot has completed. + */ + public abstract void markBootCompleted(); + + /** * Dumps various state information to the provided {@link PrintWriter} object. * * @param pw the {@link PrintWriter} object to send information to. @@ -883,6 +888,15 @@ public abstract class ApexManager { } } + @Override + public void markBootCompleted() { + try { + waitForApexService().markBootCompleted(); + } catch (RemoteException re) { + Slog.e(TAG, "Unable to contact apexservice", re); + } + } + /** * Dump information about the packages contained in a particular cache * @param packagesCache the cache to print information about. @@ -1130,6 +1144,11 @@ public abstract class ApexManager { } @Override + public void markBootCompleted() { + // No-op + } + + @Override void dump(PrintWriter pw, String packageName) { // No-op } diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 09682c664eab..39b320318302 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -1377,7 +1377,7 @@ class PackageManagerShellCommand extends ShellCommand { long timeoutMs = -1; while ((opt = getNextOption()) != null) { switch (opt) { - case "--wait": + case "--wait-for-staged-ready": waitForStagedSessionReady = true; // If there is only one remaining argument, then it represents the sessionId, we // shouldn't try to parse it as timeoutMs. @@ -2865,7 +2865,7 @@ class PackageManagerShellCommand extends ShellCommand { } sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK; break; - case "--wait": + case "--wait-for-staged-ready": params.mWaitForStagedSessionReady = true; try { params.timeoutMs = Long.parseLong(peekNextArg()); @@ -3597,7 +3597,7 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" [--preload] [--instant] [--full] [--dont-kill]"); pw.println(" [--enable-rollback]"); pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]"); - pw.println(" [--apex] [--wait TIMEOUT]"); + pw.println(" [--apex] [--wait-for-staged-ready TIMEOUT]"); pw.println(" [PATH [SPLIT...]|-]"); pw.println(" Install an application. Must provide the apk data to install, either as"); pw.println(" file path(s) or '-' to read from stdin. Options are:"); @@ -3625,8 +3625,8 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" 3=device setup, 4=user request"); pw.println(" --force-uuid: force install on to disk volume with given UUID"); pw.println(" --apex: install an .apex file, not an .apk"); - pw.println(" --wait: when performing staged install, wait TIMEOUT milliseconds"); - pw.println(" for pre-reboot verification to complete. If TIMEOUT is not"); + pw.println(" --wait-for-staged-ready: when performing staged install, wait TIMEOUT"); + pw.println(" ms for pre-reboot verification to complete. If TIMEOUT is not"); pw.println(" specified it will wait for " + DEFAULT_WAIT_MS + " milliseconds."); pw.println(""); pw.println(" install-existing [--user USER_ID|all|current]"); diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index e2bd1f1119ca..0c96f592c0db 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -164,6 +164,7 @@ public class StagingManager { public void onBootPhase(int phase) { if (phase == SystemService.PHASE_BOOT_COMPLETED && sStagingManager != null) { sStagingManager.markStagedSessionsAsSuccessful(); + sStagingManager.markBootCompleted(); } } } @@ -179,6 +180,10 @@ public class StagingManager { } } + private void markBootCompleted() { + mApexManager.markBootCompleted(); + } + /** * Validates the signature used to sign the container of the new apex package * diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp index c3fdd695c2b7..1e286bb15c49 100644 --- a/tests/StagedInstallTest/Android.bp +++ b/tests/StagedInstallTest/Android.bp @@ -24,7 +24,15 @@ java_test_host { name: "StagedInstallInternalTest", srcs: ["src/**/*.java"], libs: ["tradefed"], - static_libs: ["testng", "compatibility-tradefed"], + static_libs: [ + "testng", + "compatibility-tradefed", + "module_test_util", + ], + data: [ + ":com.android.apex.cts.shim.v2_prebuilt", + ":TestAppAv1", + ], test_suites: ["general-tests"], test_config: "StagedInstallInternalTest.xml", } diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java index 9b432f7d0ca5..86d5fd80c108 100644 --- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java @@ -19,8 +19,10 @@ package com.android.tests.stagedinstallinternal.host; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; import com.android.ddmlib.Log; +import com.android.tests.util.ModuleTestUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; import com.android.tradefed.util.ProcessInfo; @@ -30,6 +32,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.io.File; + @RunWith(DeviceJUnit4ClassRunner.class) public class StagedInstallInternalTest extends BaseHostJUnit4Test { @@ -37,6 +41,11 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { private static final long SYSTEM_SERVER_TIMEOUT_MS = 60 * 1000; private boolean mWasRoot = false; + private static final String SHIM_V2 = "com.android.apex.cts.shim.v2.apex"; + private static final String APK_A = "TestAppAv1.apk"; + + private final ModuleTestUtils mTestUtils = new ModuleTestUtils(this); + /** * Runs the given phase of a test by calling into the device. * Throws an exception if the test phase fails. @@ -87,6 +96,58 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { runPhase("testSystemServerRestartDoesNotAffectStagedSessions_Verify"); } + @Test + public void testAdbStagedInstallWaitForReadyFlagWorks() throws Exception { + assumeTrue("Device does not support updating APEX", + mTestUtils.isApexUpdateSupported()); + + File apexFile = mTestUtils.getTestFile(SHIM_V2); + String output = getDevice().executeAdbCommand("install", "--staged", + "--wait-for-staged-ready", "60000", apexFile.getAbsolutePath()); + assertThat(output).contains("Reboot device to apply staged session"); + String sessionId = getDevice().executeShellCommand( + "pm get-stagedsessions --only-ready --only-parent --only-sessionid").trim(); + assertThat(sessionId).isNotEmpty(); + } + + @Test + public void testAdbStagedInstallNoWaitFlagWorks() throws Exception { + assumeTrue("Device does not support updating APEX", + mTestUtils.isApexUpdateSupported()); + + File apexFile = mTestUtils.getTestFile(SHIM_V2); + String output = getDevice().executeAdbCommand("install", "--staged", + "--no-wait", apexFile.getAbsolutePath()); + assertThat(output).doesNotContain("Reboot device to apply staged session"); + assertThat(output).contains("Success"); + String sessionId = getDevice().executeShellCommand( + "pm get-stagedsessions --only-ready --only-parent --only-sessionid").trim(); + assertThat(sessionId).isEmpty(); + } + + @Test + public void testAdbInstallMultiPackageCommandWorks() throws Exception { + assumeTrue("Device does not support updating APEX", + mTestUtils.isApexUpdateSupported()); + + File apexFile = mTestUtils.getTestFile(SHIM_V2); + File apkFile = mTestUtils.getTestFile(APK_A); + String output = getDevice().executeAdbCommand("install-multi-package", + apexFile.getAbsolutePath(), apkFile.getAbsolutePath()); + assertThat(output).contains("Created parent session"); + assertThat(output).contains("Created child session"); + assertThat(output).contains("Success. Reboot device to apply staged session"); + + // Ensure there is only one parent session + String[] sessionIds = getDevice().executeShellCommand( + "pm get-stagedsessions --only-ready --only-parent --only-sessionid").split("\n"); + assertThat(sessionIds.length).isEqualTo(1); + // Ensure there are two children session + sessionIds = getDevice().executeShellCommand( + "pm get-stagedsessions --only-ready --only-sessionid").split("\n"); + assertThat(sessionIds.length).isEqualTo(3); + } + private void restartSystemServer() throws Exception { // Restart the system server long oldStartTime = getDevice().getProcessByName("system_server").getStartTime(); |