Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 163879ff authored by Nikita Ioffe's avatar Nikita Ioffe
Browse files

ApexManager: Request apexservice only when needed

Bug: 149060287
Test: atest --test-mapping system/apex/apexd
Test: atest ApexManagerTest
Merged-In: I2d2173a692ec95a7a35b5a24ca466917e59c1da3
Change-Id: I709210168a38202205a6a58dd5994de48f755812
parent f0edf03f
Loading
Loading
Loading
Loading
+28 −21
Original line number Diff line number Diff line
@@ -33,9 +33,9 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.os.Binder;
import android.os.Environment;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.sysprop.ApexProperties;
import android.util.Slog;

@@ -73,12 +73,7 @@ abstract class ApexManager {
     */
    static ApexManager create(Context systemContext) {
        if (ApexProperties.updatable().orElse(false)) {
            try {
                return new ApexManagerImpl(systemContext, IApexService.Stub.asInterface(
                        ServiceManager.getServiceOrThrow("apexservice")));
            } catch (ServiceManager.ServiceNotFoundException e) {
                throw new IllegalStateException("Required service apexservice not available");
            }
            return new ApexManagerImpl(systemContext);
        } else {
            return new ApexManagerFlattenedApex();
        }
@@ -247,8 +242,7 @@ abstract class ApexManager {
     * APEX packages.
     */
    @VisibleForTesting
    static class ApexManagerImpl extends ApexManager {
        private final IApexService mApexService;
    protected static class ApexManagerImpl extends ApexManager {
        private final Context mContext;
        private final Object mLock = new Object();
        /**
@@ -261,9 +255,8 @@ abstract class ApexManager {
        @GuardedBy("mLock")
        private List<PackageInfo> mAllPackagesCache;

        ApexManagerImpl(Context context, IApexService apexService) {
        ApexManagerImpl(Context context) {
            mContext = context;
            mApexService = apexService;
        }

        /**
@@ -286,10 +279,23 @@ abstract class ApexManager {
            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
        List<ActiveApexInfo> getActiveApexInfos() {
            try {
                return Arrays.stream(mApexService.getActivePackages())
                return Arrays.stream(waitForApexService().getActivePackages())
                        .map(apexInfo -> new ActiveApexInfo(
                                new File(
                                Environment.getApexDirectory() + File.separator
@@ -324,7 +330,7 @@ abstract class ApexManager {
                    mAllPackagesCache = new ArrayList<>();
                    HashSet<String> activePackagesSet = new HashSet<>();
                    HashSet<String> factoryPackagesSet = new HashSet<>();
                    final ApexInfo[] allPkgs = mApexService.getAllPackages();
                    final ApexInfo[] allPkgs = waitForApexService().getAllPackages();
                    for (ApexInfo ai : allPkgs) {
                        // If the device is using flattened APEX, don't report any APEX
                        // packages since they won't be managed or updated by PackageManager.
@@ -431,7 +437,8 @@ 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;
                }
@@ -450,7 +457,7 @@ abstract class ApexManager {
                ApexSessionParams params = new ApexSessionParams();
                params.sessionId = sessionId;
                params.childSessionIds = childSessionIds;
                mApexService.submitStagedSession(params, apexInfoList);
                waitForApexService().submitStagedSession(params, apexInfoList);
                return apexInfoList;
            } catch (RemoteException re) {
                Slog.e(TAG, "Unable to contact apexservice", re);
@@ -465,7 +472,7 @@ 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);
@@ -479,7 +486,7 @@ 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);
@@ -498,7 +505,7 @@ abstract class ApexManager {
        @Override
        boolean revertActiveSessions() {
            try {
                mApexService.revertActiveSessions();
                waitForApexService().revertActiveSessions();
                return true;
            } catch (RemoteException re) {
                Slog.e(TAG, "Unable to contact apexservice", re);
@@ -512,7 +519,7 @@ 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);
@@ -527,7 +534,7 @@ 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;
@@ -578,7 +585,7 @@ abstract class ApexManager {
                ipw.increaseIndent();
                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();
+5 −1
Original line number Diff line number Diff line
@@ -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;
@@ -68,7 +70,9 @@ public class ApexManagerTest {
    @Before
    public void setUp() throws RemoteException {
        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