summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jon Spivack <spivack@google.com> 2020-02-06 18:46:45 -0800
committer Jon Spivack <spivack@google.com> 2020-03-26 22:11:50 -0700
commit91baff97827dfaad5a01e369c3d69c644a3e5746 (patch)
tree8eb0f834689b35e00c7cd07c764dff4f1d2685b3
parent5b2f94a0aa5b0324aae375a6330b3e09f90800d0 (diff)
ApexManager: Request apexservice only when needed
Replacing the reference to apexservice with individual requests allows the service to be dynamically stopped when not in use and started on demand. Bug: 149060287 Test: atest --test-mapping system/apex/apexd Test: atest ApexManagerTest Change-Id: I2d2173a692ec95a7a35b5a24ca466917e59c1da3
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java60
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java7
2 files changed, 37 insertions, 30 deletions
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index c97f33b5103f..e90dc1306c29 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -32,9 +32,9 @@ import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
+import android.os.Binder;
import android.os.Environment;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.Trace;
import android.sysprop.ApexProperties;
import android.util.ArrayMap;
@@ -61,7 +61,6 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
@@ -83,13 +82,7 @@ public abstract class ApexManager {
@Override
protected ApexManager create() {
if (ApexProperties.updatable().orElse(false)) {
- try {
- return new ApexManagerImpl(IApexService.Stub.asInterface(
- ServiceManager.getServiceOrThrow("apexservice")));
- } catch (ServiceManager.ServiceNotFoundException e) {
- throw new IllegalStateException(
- "Required service apexservice not available");
- }
+ return new ApexManagerImpl();
} else {
return new ApexManagerFlattenedApex();
}
@@ -360,8 +353,7 @@ public abstract class ApexManager {
* APEX packages.
*/
@VisibleForTesting
- static class ApexManagerImpl extends ApexManager {
- private final IApexService mApexService;
+ protected static class ApexManagerImpl extends ApexManager {
private final Object mLock = new Object();
@GuardedBy("mLock")
@@ -390,10 +382,6 @@ public abstract class ApexManager {
@GuardedBy("mLock")
private ArrayMap<String, String> mPackageNameToApexModuleName;
- ApexManagerImpl(IApexService apexService) {
- mApexService = apexService;
- }
-
/**
* Whether an APEX package is active or not.
*
@@ -404,6 +392,19 @@ public abstract class ApexManager {
return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
}
+ /**
+ * Retrieve the service from ServiceManager. If the service is not running, it will be
+ * started, and this function will block until it is ready.
+ */
+ @VisibleForTesting
+ protected IApexService waitForApexService() {
+ try {
+ return IApexService.Stub.asInterface(Binder.waitForService("apexservice"));
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Required service apexservice not available");
+ }
+ }
+
@Override
public List<ActiveApexInfo> getActiveApexInfos() {
final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
@@ -413,7 +414,7 @@ public abstract class ApexManager {
t.traceBegin("getActiveApexInfos_noCache");
try {
mActiveApexInfosCache = new ArraySet<>();
- final ApexInfo[] activePackages = mApexService.getActivePackages();
+ final ApexInfo[] activePackages = waitForApexService().getActivePackages();
for (int i = 0; i < activePackages.length; i++) {
ApexInfo apexInfo = activePackages[i];
mActiveApexInfosCache.add(new ActiveApexInfo(apexInfo));
@@ -451,7 +452,7 @@ public abstract class ApexManager {
try {
mAllPackagesCache = new ArrayList<>();
mPackageNameToApexModuleName = new ArrayMap<>();
- allPkgs = mApexService.getAllPackages();
+ allPkgs = waitForApexService().getAllPackages();
} catch (RemoteException re) {
Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
throw new RuntimeException(re);
@@ -610,7 +611,8 @@ public abstract class ApexManager {
@Override
@Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) {
try {
- ApexSessionInfo apexSessionInfo = mApexService.getStagedSessionInfo(sessionId);
+ ApexSessionInfo apexSessionInfo =
+ waitForApexService().getStagedSessionInfo(sessionId);
if (apexSessionInfo.isUnknown) {
return null;
}
@@ -625,7 +627,7 @@ public abstract class ApexManager {
ApexInfoList submitStagedSession(ApexSessionParams params) throws PackageManagerException {
try {
final ApexInfoList apexInfoList = new ApexInfoList();
- mApexService.submitStagedSession(params, apexInfoList);
+ waitForApexService().submitStagedSession(params, apexInfoList);
return apexInfoList;
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
@@ -640,7 +642,7 @@ public abstract class ApexManager {
@Override
void markStagedSessionReady(int sessionId) throws PackageManagerException {
try {
- mApexService.markStagedSessionReady(sessionId);
+ waitForApexService().markStagedSessionReady(sessionId);
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
throw new RuntimeException(re);
@@ -654,7 +656,7 @@ public abstract class ApexManager {
@Override
void markStagedSessionSuccessful(int sessionId) {
try {
- mApexService.markStagedSessionSuccessful(sessionId);
+ waitForApexService().markStagedSessionSuccessful(sessionId);
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
throw new RuntimeException(re);
@@ -673,7 +675,7 @@ public abstract class ApexManager {
@Override
boolean revertActiveSessions() {
try {
- mApexService.revertActiveSessions();
+ waitForApexService().revertActiveSessions();
return true;
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
@@ -687,7 +689,7 @@ public abstract class ApexManager {
@Override
boolean abortStagedSession(int sessionId) throws PackageManagerException {
try {
- mApexService.abortStagedSession(sessionId);
+ waitForApexService().abortStagedSession(sessionId);
return true;
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
@@ -702,7 +704,7 @@ public abstract class ApexManager {
@Override
boolean uninstallApex(String apexPackagePath) {
try {
- mApexService.unstagePackages(Collections.singletonList(apexPackagePath));
+ waitForApexService().unstagePackages(Collections.singletonList(apexPackagePath));
return true;
} catch (Exception e) {
return false;
@@ -763,7 +765,7 @@ public abstract class ApexManager {
return -1;
}
try {
- return mApexService.snapshotCeData(userId, rollbackId, apexModuleName);
+ return waitForApexService().snapshotCeData(userId, rollbackId, apexModuleName);
} catch (Exception e) {
Slog.e(TAG, e.getMessage(), e);
return -1;
@@ -783,7 +785,7 @@ public abstract class ApexManager {
return false;
}
try {
- mApexService.restoreCeData(userId, rollbackId, apexModuleName);
+ waitForApexService().restoreCeData(userId, rollbackId, apexModuleName);
return true;
} catch (Exception e) {
Slog.e(TAG, e.getMessage(), e);
@@ -794,7 +796,7 @@ public abstract class ApexManager {
@Override
public boolean destroyDeSnapshots(int rollbackId) {
try {
- mApexService.destroyDeSnapshots(rollbackId);
+ waitForApexService().destroyDeSnapshots(rollbackId);
return true;
} catch (Exception e) {
Slog.e(TAG, e.getMessage(), e);
@@ -805,7 +807,7 @@ public abstract class ApexManager {
@Override
public boolean destroyCeSnapshotsNotSpecified(int userId, int[] retainRollbackIds) {
try {
- mApexService.destroyCeSnapshotsNotSpecified(userId, retainRollbackIds);
+ waitForApexService().destroyCeSnapshotsNotSpecified(userId, retainRollbackIds);
return true;
} catch (Exception e) {
Slog.e(TAG, e.getMessage(), e);
@@ -849,7 +851,7 @@ public abstract class ApexManager {
ipw.println();
ipw.println("APEX session state:");
ipw.increaseIndent();
- final ApexSessionInfo[] sessions = mApexService.getSessions();
+ final ApexSessionInfo[] sessions = waitForApexService().getSessions();
for (ApexSessionInfo si : sessions) {
ipw.println("Session ID: " + si.sessionId);
ipw.increaseIndent();
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index db1bbab7ed94..73e5b6ddfb1d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -21,8 +21,10 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -58,6 +60,7 @@ import java.io.InputStream;
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
+
public class ApexManagerTest {
private static final String TEST_APEX_PKG = "com.android.apex.test";
private static final int TEST_SESSION_ID = 99999999;
@@ -71,7 +74,9 @@ public class ApexManagerTest {
@Before
public void setUp() throws RemoteException {
mContext = InstrumentationRegistry.getInstrumentation().getContext();
- mApexManager = new ApexManager.ApexManagerImpl(mApexService);
+ ApexManager.ApexManagerImpl managerImpl = spy(new ApexManager.ApexManagerImpl());
+ doReturn(mApexService).when(managerImpl).waitForApexService();
+ mApexManager = managerImpl;
mPackageParser2 = new PackageParser2(null, false, null, null, null);
}