Merge "ApexManager: Request apexservice only when needed" am: d96b6a6823

Change-Id: If80283b5cb9e479fcfa8c4fdea21fa2da03266bc
This commit is contained in:
Nikita Ioffe
2020-05-19 12:12:49 +00:00
committed by Automerger Merge Worker
2 changed files with 33 additions and 22 deletions

View File

@@ -33,9 +33,9 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller; import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageParser; import android.content.pm.PackageParser;
import android.os.Binder;
import android.os.Environment; import android.os.Environment;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager;
import android.sysprop.ApexProperties; import android.sysprop.ApexProperties;
import android.util.Slog; import android.util.Slog;
@@ -73,12 +73,7 @@ abstract class ApexManager {
*/ */
static ApexManager create(Context systemContext) { static ApexManager create(Context systemContext) {
if (ApexProperties.updatable().orElse(false)) { if (ApexProperties.updatable().orElse(false)) {
try { return new ApexManagerImpl(systemContext);
return new ApexManagerImpl(systemContext, IApexService.Stub.asInterface(
ServiceManager.getServiceOrThrow("apexservice")));
} catch (ServiceManager.ServiceNotFoundException e) {
throw new IllegalStateException("Required service apexservice not available");
}
} else { } else {
return new ApexManagerFlattenedApex(); return new ApexManagerFlattenedApex();
} }
@@ -247,8 +242,7 @@ abstract class ApexManager {
* APEX packages. * APEX packages.
*/ */
@VisibleForTesting @VisibleForTesting
static class ApexManagerImpl extends ApexManager { protected static class ApexManagerImpl extends ApexManager {
private final IApexService mApexService;
private final Context mContext; private final Context mContext;
private final Object mLock = new Object(); private final Object mLock = new Object();
/** /**
@@ -261,9 +255,8 @@ abstract class ApexManager {
@GuardedBy("mLock") @GuardedBy("mLock")
private List<PackageInfo> mAllPackagesCache; private List<PackageInfo> mAllPackagesCache;
ApexManagerImpl(Context context, IApexService apexService) { ApexManagerImpl(Context context) {
mContext = context; mContext = context;
mApexService = apexService;
} }
/** /**
@@ -286,10 +279,23 @@ abstract class ApexManager {
return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 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 @Override
List<ActiveApexInfo> getActiveApexInfos() { List<ActiveApexInfo> getActiveApexInfos() {
try { try {
return Arrays.stream(mApexService.getActivePackages()) return Arrays.stream(waitForApexService().getActivePackages())
.map(apexInfo -> new ActiveApexInfo( .map(apexInfo -> new ActiveApexInfo(
new File( new File(
Environment.getApexDirectory() + File.separator Environment.getApexDirectory() + File.separator
@@ -324,7 +330,7 @@ abstract class ApexManager {
mAllPackagesCache = new ArrayList<>(); mAllPackagesCache = new ArrayList<>();
HashSet<String> activePackagesSet = new HashSet<>(); HashSet<String> activePackagesSet = new HashSet<>();
HashSet<String> factoryPackagesSet = new HashSet<>(); HashSet<String> factoryPackagesSet = new HashSet<>();
final ApexInfo[] allPkgs = mApexService.getAllPackages(); final ApexInfo[] allPkgs = waitForApexService().getAllPackages();
for (ApexInfo ai : allPkgs) { for (ApexInfo ai : allPkgs) {
// If the device is using flattened APEX, don't report any APEX // If the device is using flattened APEX, don't report any APEX
// packages since they won't be managed or updated by PackageManager. // packages since they won't be managed or updated by PackageManager.
@@ -431,7 +437,8 @@ abstract class ApexManager {
@Override @Override
@Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) { @Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) {
try { try {
ApexSessionInfo apexSessionInfo = mApexService.getStagedSessionInfo(sessionId); ApexSessionInfo apexSessionInfo =
waitForApexService().getStagedSessionInfo(sessionId);
if (apexSessionInfo.isUnknown) { if (apexSessionInfo.isUnknown) {
return null; return null;
} }
@@ -450,7 +457,7 @@ abstract class ApexManager {
ApexSessionParams params = new ApexSessionParams(); ApexSessionParams params = new ApexSessionParams();
params.sessionId = sessionId; params.sessionId = sessionId;
params.childSessionIds = childSessionIds; params.childSessionIds = childSessionIds;
mApexService.submitStagedSession(params, apexInfoList); waitForApexService().submitStagedSession(params, apexInfoList);
return apexInfoList; return apexInfoList;
} catch (RemoteException re) { } catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re); Slog.e(TAG, "Unable to contact apexservice", re);
@@ -465,7 +472,7 @@ abstract class ApexManager {
@Override @Override
void markStagedSessionReady(int sessionId) throws PackageManagerException { void markStagedSessionReady(int sessionId) throws PackageManagerException {
try { try {
mApexService.markStagedSessionReady(sessionId); waitForApexService().markStagedSessionReady(sessionId);
} catch (RemoteException re) { } catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re); Slog.e(TAG, "Unable to contact apexservice", re);
throw new RuntimeException(re); throw new RuntimeException(re);
@@ -479,7 +486,7 @@ abstract class ApexManager {
@Override @Override
void markStagedSessionSuccessful(int sessionId) { void markStagedSessionSuccessful(int sessionId) {
try { try {
mApexService.markStagedSessionSuccessful(sessionId); waitForApexService().markStagedSessionSuccessful(sessionId);
} catch (RemoteException re) { } catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re); Slog.e(TAG, "Unable to contact apexservice", re);
throw new RuntimeException(re); throw new RuntimeException(re);
@@ -498,7 +505,7 @@ abstract class ApexManager {
@Override @Override
boolean revertActiveSessions() { boolean revertActiveSessions() {
try { try {
mApexService.revertActiveSessions(); waitForApexService().revertActiveSessions();
return true; return true;
} catch (RemoteException re) { } catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re); Slog.e(TAG, "Unable to contact apexservice", re);
@@ -512,7 +519,7 @@ abstract class ApexManager {
@Override @Override
boolean abortStagedSession(int sessionId) throws PackageManagerException { boolean abortStagedSession(int sessionId) throws PackageManagerException {
try { try {
mApexService.abortStagedSession(sessionId); waitForApexService().abortStagedSession(sessionId);
return true; return true;
} catch (RemoteException re) { } catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re); Slog.e(TAG, "Unable to contact apexservice", re);
@@ -527,7 +534,7 @@ abstract class ApexManager {
@Override @Override
boolean uninstallApex(String apexPackagePath) { boolean uninstallApex(String apexPackagePath) {
try { try {
mApexService.unstagePackages(Collections.singletonList(apexPackagePath)); waitForApexService().unstagePackages(Collections.singletonList(apexPackagePath));
return true; return true;
} catch (Exception e) { } catch (Exception e) {
return false; return false;
@@ -578,7 +585,7 @@ abstract class ApexManager {
ipw.increaseIndent(); ipw.increaseIndent();
ipw.println("APEX session state:"); ipw.println("APEX session state:");
ipw.increaseIndent(); ipw.increaseIndent();
final ApexSessionInfo[] sessions = mApexService.getSessions(); final ApexSessionInfo[] sessions = waitForApexService().getSessions();
for (ApexSessionInfo si : sessions) { for (ApexSessionInfo si : sessions) {
ipw.println("Session ID: " + si.sessionId); ipw.println("Session ID: " + si.sessionId);
ipw.increaseIndent(); ipw.increaseIndent();

View File

@@ -21,8 +21,10 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -68,7 +70,9 @@ public class ApexManagerTest {
@Before @Before
public void setUp() throws RemoteException { public void setUp() throws RemoteException {
mContext = InstrumentationRegistry.getInstrumentation().getContext(); mContext = InstrumentationRegistry.getInstrumentation().getContext();
mApexManager = new ApexManager.ApexManagerImpl(mContext, mApexService); ApexManager.ApexManagerImpl managerImpl = spy(new ApexManager.ApexManagerImpl(mContext));
doReturn(mApexService).when(managerImpl).waitForApexService();
mApexManager = managerImpl;
} }
@Test @Test