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

Commit 9ade5e2f authored by Mohammad Samiul Islam's avatar Mohammad Samiul Islam Committed by Android (Google) Code Review
Browse files

Merge changes from topic "compos-cherry-pick" into stage-aosp-master

* changes:
  Hook the new APIs in StagingManager to PackageManagerNative service
  Notify StagedApexObservers when there is a change in set of staged APEX
  Open up new API in StagingManager to get information about staged APEX
  Connect the new API from ApexService to ApexManager
parents 0c08393b 818cbce3
Loading
Loading
Loading
Loading
+26 −0
Original line number Original line Diff line number Diff line
@@ -248,6 +248,14 @@ public abstract class ApexManager {
    abstract ApexInfoList submitStagedSession(ApexSessionParams params)
    abstract ApexInfoList submitStagedSession(ApexSessionParams params)
            throws PackageManagerException;
            throws PackageManagerException;


    /**
     * Returns {@code ApeInfo} about apex sessions that have been marked ready via
     * {@link #markStagedSessionReady(int)}
     *
     * Returns empty array if there is no staged apex session or if there is any error.
     */
    abstract ApexInfo[] getStagedApexInfos(ApexSessionParams params);

    /**
    /**
     * Mark a staged session previously submitted using {@code submitStagedSession} as ready to be
     * Mark a staged session previously submitted using {@code submitStagedSession} as ready to be
     * applied at next reboot.
     * applied at next reboot.
@@ -756,6 +764,19 @@ public abstract class ApexManager {
            }
            }
        }
        }


        @Override
        ApexInfo[] getStagedApexInfos(ApexSessionParams params) {
            try {
                return waitForApexService().getStagedApexInfos(params);
            } catch (RemoteException re) {
                Slog.w(TAG, "Unable to contact apexservice" + re.getMessage());
                throw new RuntimeException(re);
            } catch (Exception e) {
                Slog.w(TAG, "Failed to collect staged apex infos" + e.getMessage());
                return new ApexInfo[0];
            }
        }

        @Override
        @Override
        void markStagedSessionReady(int sessionId) throws PackageManagerException {
        void markStagedSessionReady(int sessionId) throws PackageManagerException {
            try {
            try {
@@ -1246,6 +1267,11 @@ public abstract class ApexManager {
                    "Device doesn't support updating APEX");
                    "Device doesn't support updating APEX");
        }
        }


        @Override
        ApexInfo[] getStagedApexInfos(ApexSessionParams params) {
            throw new UnsupportedOperationException();
        }

        @Override
        @Override
        void markStagedSessionReady(int sessionId) {
        void markStagedSessionReady(int sessionId) {
            throw new UnsupportedOperationException();
            throw new UnsupportedOperationException();
+4 −0
Original line number Original line Diff line number Diff line
@@ -260,6 +260,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
                new Lifecycle(context, this));
                new Lifecycle(context, this));
    }
    }


    StagingManager getStagingManager() {
        return mStagingManager;
    }

    boolean okToSendBroadcasts()  {
    boolean okToSendBroadcasts()  {
        return mOkToSendBroadcasts;
        return mOkToSendBroadcasts;
    }
    }
+25 −0
Original line number Original line Diff line number Diff line
@@ -186,6 +186,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.IPackageManagerNative;
import android.content.pm.IPackageManagerNative;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.IStagedApexObserver;
import android.content.pm.IncrementalStatesInfo;
import android.content.pm.IncrementalStatesInfo;
import android.content.pm.InstallSourceInfo;
import android.content.pm.InstallSourceInfo;
import android.content.pm.InstantAppInfo;
import android.content.pm.InstantAppInfo;
@@ -227,6 +228,7 @@ import android.content.pm.ServiceInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.Signature;
import android.content.pm.Signature;
import android.content.pm.SigningInfo;
import android.content.pm.SigningInfo;
import android.content.pm.StagedApexInfo;
import android.content.pm.SuspendDialogInfo;
import android.content.pm.SuspendDialogInfo;
import android.content.pm.TestUtilityService;
import android.content.pm.TestUtilityService;
import android.content.pm.UserInfo;
import android.content.pm.UserInfo;
@@ -27003,6 +27005,29 @@ public class PackageManagerService extends IPackageManager.Stub
        public boolean hasSystemFeature(String featureName, int version) {
        public boolean hasSystemFeature(String featureName, int version) {
            return PackageManagerService.this.hasSystemFeature(featureName, version);
            return PackageManagerService.this.hasSystemFeature(featureName, version);
        }
        }
        @Override
        public void registerStagedApexObserver(IStagedApexObserver observer) {
            mInstallerService.getStagingManager().registerStagedApexObserver(observer);
        }
        @Override
        public void unregisterStagedApexObserver(IStagedApexObserver observer) {
            mInstallerService.getStagingManager().unregisterStagedApexObserver(observer);
        }
        @Override
        public String[] getStagedApexModuleNames() {
            return mInstallerService.getStagingManager()
                    .getStagedApexModuleNames().toArray(new String[0]);
        }
        @Override
        @Nullable
        public StagedApexInfo getStagedApexInfo(String moduleName) {
            return mInstallerService.getStagingManager().getStagedApexInfo(moduleName);
        }
    }
    }
    private AndroidPackage getPackage(String packageName) {
    private AndroidPackage getPackage(String packageName) {
+148 −3
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.pm;
package com.android.server.pm;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.apex.ApexInfo;
import android.apex.ApexInfo;
import android.apex.ApexInfoList;
import android.apex.ApexInfoList;
import android.apex.ApexSessionInfo;
import android.apex.ApexSessionInfo;
@@ -28,7 +29,9 @@ import android.content.IIntentSender;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.IntentSender;
import android.content.pm.ApexStagedEvent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IStagedApexObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageInstaller.SessionInfo;
@@ -38,6 +41,7 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageParser.SigningDetails;
import android.content.pm.PackageParser.SigningDetails;
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
import android.content.pm.StagedApexInfo;
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.content.rollback.RollbackManager;
@@ -52,6 +56,7 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserHandle;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.IntArray;
import android.util.Slog;
import android.util.Slog;
@@ -80,7 +85,9 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit;
@@ -98,7 +105,8 @@ public class StagingManager {
    private final ApexManager mApexManager;
    private final ApexManager mApexManager;
    private final PowerManager mPowerManager;
    private final PowerManager mPowerManager;
    private final Context mContext;
    private final Context mContext;
    private final PreRebootVerificationHandler mPreRebootVerificationHandler;
    @VisibleForTesting
    final PreRebootVerificationHandler mPreRebootVerificationHandler;
    private final Supplier<PackageParser2> mPackageParserSupplier;
    private final Supplier<PackageParser2> mPackageParserSupplier;


    private final File mFailureReasonFile = new File("/metadata/staged-install/failure_reason.txt");
    private final File mFailureReasonFile = new File("/metadata/staged-install/failure_reason.txt");
@@ -114,6 +122,9 @@ public class StagingManager {
    @GuardedBy("mSuccessfulStagedSessionIds")
    @GuardedBy("mSuccessfulStagedSessionIds")
    private final List<Integer> mSuccessfulStagedSessionIds = new ArrayList<>();
    private final List<Integer> mSuccessfulStagedSessionIds = new ArrayList<>();


    @GuardedBy("mStagedApexObservers")
    private final List<IStagedApexObserver> mStagedApexObservers = new ArrayList<>();

    interface StagedSession {
    interface StagedSession {
        boolean isMultiPackage();
        boolean isMultiPackage();
        boolean isApexSession();
        boolean isApexSession();
@@ -198,6 +209,35 @@ public class StagingManager {
        mApexManager.markBootCompleted();
        mApexManager.markBootCompleted();
    }
    }


    void registerStagedApexObserver(IStagedApexObserver observer) {
        if (observer == null) {
            return;
        }
        if  (observer.asBinder() != null) {
            try {
                observer.asBinder().linkToDeath(new IBinder.DeathRecipient() {
                    @Override
                    public void binderDied() {
                        synchronized (mStagedApexObservers) {
                            mStagedApexObservers.remove(observer);
                        }
                    }
                }, 0);
            } catch (RemoteException re) {
                Slog.w(TAG, re.getMessage());
            }
        }
        synchronized (mStagedApexObservers) {
            mStagedApexObservers.add(observer);
        }
    }

    void unregisterStagedApexObserver(IStagedApexObserver observer) {
        synchronized (mStagedApexObservers) {
            mStagedApexObservers.remove(observer);
        }
    }

    /**
    /**
     * Validates the signature used to sign the container of the new apex package
     * Validates the signature used to sign the container of the new apex package
     *
     *
@@ -836,6 +876,9 @@ public class StagingManager {
                // Also, cleaning up the stageDir prevents the apex from being activated.
                // Also, cleaning up the stageDir prevents the apex from being activated.
                Slog.e(TAG, "Failed to abort apex session " + session.sessionId());
                Slog.e(TAG, "Failed to abort apex session " + session.sessionId());
            }
            }
            if (session.containsApexSession()) {
                notifyStagedApexObservers();
            }
        }
        }


        // Session was successfully aborted from apexd (if required) and pre-reboot verification
        // Session was successfully aborted from apexd (if required) and pre-reboot verification
@@ -1134,7 +1177,107 @@ public class StagingManager {
        mPreRebootVerificationHandler.notifyPreRebootVerification_Apk_Complete(session);
        mPreRebootVerificationHandler.notifyPreRebootVerification_Apk_Complete(session);
    }
    }


    private final class PreRebootVerificationHandler extends Handler {
    /**
     * Returns ApexInfo about APEX contained inside the session as a {@code Map<String, ApexInfo>},
     * where the key of the map is the module name of the ApexInfo.
     *
     * Returns an empty map if there is any error.
     */
    @VisibleForTesting
    @NonNull
    Map<String, ApexInfo> getStagedApexInfos(@NonNull StagedSession session) {
        Preconditions.checkArgument(session != null, "Session is null");
        Preconditions.checkArgument(!session.hasParentSessionId(),
                session.sessionId() + " session has parent session");
        Preconditions.checkArgument(session.containsApexSession(),
                session.sessionId() + " session does not contain apex");

        // Even if caller calls this method on ready session, the session could be abandoned
        // right after this method is called.
        if (!session.isSessionReady() || session.isDestroyed()) {
            return Collections.emptyMap();
        }

        ApexSessionParams params = new ApexSessionParams();
        params.sessionId = session.sessionId();
        final IntArray childSessionIds = new IntArray();
        if (session.isMultiPackage()) {
            for (StagedSession s : session.getChildSessions()) {
                if (s.isApexSession()) {
                    childSessionIds.add(s.sessionId());
                }
            }
        }
        params.childSessionIds = childSessionIds.toArray();

        ApexInfo[] infos = mApexManager.getStagedApexInfos(params);
        Map<String, ApexInfo> result = new ArrayMap<>();
        for (ApexInfo info : infos) {
            result.put(info.moduleName, info);
        }
        return result;
    }

    /**
     * Returns apex module names of all packages that are staged ready
     */
    List<String> getStagedApexModuleNames() {
        List<String> result = new ArrayList<>();
        synchronized (mStagedSessions) {
            for (int i = 0; i < mStagedSessions.size(); i++) {
                final StagedSession session = mStagedSessions.valueAt(i);
                if (!session.isSessionReady() || session.isDestroyed()
                        || session.hasParentSessionId() || !session.containsApexSession()) {
                    continue;
                }
                result.addAll(getStagedApexInfos(session).keySet());
            }
        }
        return result;
    }

    /**
     * Returns ApexInfo of the {@code moduleInfo} provided if it is staged, otherwise returns null.
     */
    @Nullable
    StagedApexInfo getStagedApexInfo(String moduleName) {
        synchronized (mStagedSessions) {
            for (int i = 0; i < mStagedSessions.size(); i++) {
                final StagedSession session = mStagedSessions.valueAt(i);
                if (!session.isSessionReady() || session.isDestroyed()
                        || session.hasParentSessionId() || !session.containsApexSession()) {
                    continue;
                }
                ApexInfo ai = getStagedApexInfos(session).get(moduleName);
                if (ai != null) {
                    StagedApexInfo info = new StagedApexInfo();
                    info.moduleName = ai.moduleName;
                    info.diskImagePath = ai.modulePath;
                    info.versionCode = ai.versionCode;
                    info.versionName = ai.versionName;
                    return info;
                }
            }
        }
        return null;
    }

    private void notifyStagedApexObservers() {
        synchronized (mStagedApexObservers) {
            for (IStagedApexObserver observer : mStagedApexObservers) {
                ApexStagedEvent event = new ApexStagedEvent();
                event.stagedApexModuleNames = getStagedApexModuleNames().toArray(new String[0]);
                try {
                    observer.onApexStaged(event);
                } catch (RemoteException re) {
                    Slog.w(TAG, "Failed to contact the observer " + re.getMessage());
                }
            }
        }
    }

    @VisibleForTesting
    final class PreRebootVerificationHandler extends Handler {
        // Hold sessions before handler gets ready to do the verification.
        // Hold sessions before handler gets ready to do the verification.
        private List<StagedSession> mPendingSessions;
        private List<StagedSession> mPendingSessions;
        private boolean mIsReady;
        private boolean mIsReady;
@@ -1160,7 +1303,8 @@ public class StagingManager {
        private static final int MSG_PRE_REBOOT_VERIFICATION_START = 1;
        private static final int MSG_PRE_REBOOT_VERIFICATION_START = 1;
        private static final int MSG_PRE_REBOOT_VERIFICATION_APEX = 2;
        private static final int MSG_PRE_REBOOT_VERIFICATION_APEX = 2;
        private static final int MSG_PRE_REBOOT_VERIFICATION_APK = 3;
        private static final int MSG_PRE_REBOOT_VERIFICATION_APK = 3;
        private static final int MSG_PRE_REBOOT_VERIFICATION_END = 4;
        @VisibleForTesting
        static final int MSG_PRE_REBOOT_VERIFICATION_END = 4;


        @Override
        @Override
        public void handleMessage(Message msg) {
        public void handleMessage(Message msg) {
@@ -1402,6 +1546,7 @@ public class StagingManager {
                if (hasApex) {
                if (hasApex) {
                    try {
                    try {
                        mApexManager.markStagedSessionReady(session.sessionId());
                        mApexManager.markStagedSessionReady(session.sessionId());
                        notifyStagedApexObservers();
                    } catch (PackageManagerException e) {
                    } catch (PackageManagerException e) {
                        session.setSessionFailed(e.error, e.getMessage());
                        session.setSessionFailed(e.error, e.getMessage());
                        return;
                        return;
+296 −5

File changed.

Preview size limit exceeded, changes collapsed.

Loading