Factor out calls to apexservice in a class.
The ApexManager class provides a cleaner interface to the apex service, as well as providing caching for active packages, which can't change on a running system. The cache is populated at boot time. This CL will also cause PackageManager to stop reporting APEX packages on devices that ship with flattened APEXs. Test: atest apex_e2e_tests; used small app to verify API calls still work; checked output of dumpsys. Test: checked that on marlin (target with flatten APEX) no APEXs are reported and no crashes are experienced at boot. Fix: 123052859 Fix: 122638509 Fix: 124299505 Bug: 122952270 Change-Id: Iefe4fb42e455a7479ff47eb776d3492de8395469
This commit is contained in:
221
services/core/java/com/android/server/pm/ApexManager.java
Normal file
221
services/core/java/com/android/server/pm/ApexManager.java
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.s
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.apex.ApexInfo;
|
||||
import android.apex.ApexInfoList;
|
||||
import android.apex.ApexSessionInfo;
|
||||
import android.apex.IApexService;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageParser;
|
||||
import android.content.pm.PackageParser.PackageParserException;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* ApexManager class handles communications with the apex service to perform operation and queries,
|
||||
* as well as providing caching to avoid unnecessary calls to the service.
|
||||
*/
|
||||
class ApexManager {
|
||||
static final String TAG = "ApexManager";
|
||||
private final IApexService mApexService;
|
||||
private final Map<String, PackageInfo> mActivePackagesCache;
|
||||
|
||||
ApexManager() {
|
||||
mApexService = IApexService.Stub.asInterface(
|
||||
ServiceManager.getService("apexservice"));
|
||||
mActivePackagesCache = populateActivePackagesCache();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Map<String, PackageInfo> populateActivePackagesCache() {
|
||||
try {
|
||||
List<PackageInfo> list = new ArrayList<>();
|
||||
final ApexInfo[] activePkgs = mApexService.getActivePackages();
|
||||
for (ApexInfo ai : activePkgs) {
|
||||
// If the device is using flattened APEX, don't report any APEX
|
||||
// packages since they won't be managed or updated by PackageManager.
|
||||
if ((new File(ai.packagePath)).isDirectory()) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
list.add(PackageParser.generatePackageInfoFromApex(
|
||||
new File(ai.packagePath), true /* collect certs */));
|
||||
} catch (PackageParserException pe) {
|
||||
throw new IllegalStateException("Unable to parse: " + ai, pe);
|
||||
}
|
||||
}
|
||||
return list.stream().collect(Collectors.toMap(p -> p.packageName, Function.identity()));
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
|
||||
throw new RuntimeException(re);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information about an active APEX package.
|
||||
*
|
||||
* @param packageName the package name to look for. Note that this is the package name reported
|
||||
* in the APK container manifest (i.e. AndroidManifest.xml), which might
|
||||
* differ from the one reported in the APEX manifest (i.e.
|
||||
* apex_manifest.json).
|
||||
* @return a PackageInfo object with the information about the package, or null if the package
|
||||
* is not found.
|
||||
*/
|
||||
@Nullable PackageInfo getActivePackage(String packageName) {
|
||||
return mActivePackagesCache.get(packageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information about all active APEX packages.
|
||||
*
|
||||
* @return a Collection of PackageInfo object, each one containing information about a different
|
||||
* active package.
|
||||
*/
|
||||
Collection<PackageInfo> getActivePackages() {
|
||||
return mActivePackagesCache.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information about an apexd staged session i.e. the internal state used by apexd to
|
||||
* track the different states of a session.
|
||||
*
|
||||
* @param sessionId the identifier of the session.
|
||||
* @return an ApexSessionInfo object, or null if the session is not known.
|
||||
*/
|
||||
@Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) {
|
||||
try {
|
||||
ApexSessionInfo apexSessionInfo = mApexService.getStagedSessionInfo(sessionId);
|
||||
if (apexSessionInfo.isUnknown) {
|
||||
return null;
|
||||
}
|
||||
return apexSessionInfo;
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(TAG, "Unable to contact apexservice", re);
|
||||
throw new RuntimeException(re);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit a staged session to apex service. This causes the apex service to perform some initial
|
||||
* verification and accept or reject the session. Submitting a session successfully is not
|
||||
* enough for it to be activated at the next boot, the caller needs to call
|
||||
* {@link #markStagedSessionReady(int)}.
|
||||
*
|
||||
* @param sessionId the identifier of the {@link PackageInstallerSession} being submitted.
|
||||
* @param childSessionIds if {@code sessionId} is a multi-package session, this should contain
|
||||
* an array of identifiers of all the child sessions. Otherwise it should
|
||||
* be an empty array.
|
||||
* @param apexInfoList this is an output parameter, which needs to be initialized by tha caller
|
||||
* and will be filled with a list of {@link ApexInfo} objects, each of which
|
||||
* contains metadata about one of the packages being submitted as part of
|
||||
* the session.
|
||||
* @return whether the submission of the session was successful.
|
||||
*/
|
||||
boolean submitStagedSession(
|
||||
int sessionId, @NonNull int[] childSessionIds, @NonNull ApexInfoList apexInfoList) {
|
||||
try {
|
||||
return mApexService.submitStagedSession(sessionId, childSessionIds, apexInfoList);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(TAG, "Unable to contact apexservice", re);
|
||||
throw new RuntimeException(re);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a staged session previously submitted using {@cde submitStagedSession} as ready to be
|
||||
* applied at next reboot.
|
||||
*
|
||||
* @param sessionId the identifier of the {@link PackageInstallerSession} being marked as ready.
|
||||
* @return true upon success, false if the session is unknown.
|
||||
*/
|
||||
boolean markStagedSessionReady(int sessionId) {
|
||||
try {
|
||||
return mApexService.markStagedSessionReady(sessionId);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(TAG, "Unable to contact apexservice", re);
|
||||
throw new RuntimeException(re);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps various state information to the provided {@link PrintWriter} object.
|
||||
*
|
||||
* @param pw the {@link PrintWriter} object to send information to.
|
||||
* @param packageName a {@link String} containing a package name, or {@code null}. If set, only
|
||||
* information about that specific package will be dumped.
|
||||
*/
|
||||
void dump(PrintWriter pw, @Nullable String packageName) {
|
||||
final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
|
||||
ipw.println();
|
||||
ipw.println("Active APEX packages:");
|
||||
ipw.increaseIndent();
|
||||
try {
|
||||
populateActivePackagesCache();
|
||||
for (PackageInfo pi : mActivePackagesCache.values()) {
|
||||
if (packageName != null && !packageName.equals(pi.packageName)) {
|
||||
continue;
|
||||
}
|
||||
ipw.println(pi.packageName);
|
||||
ipw.increaseIndent();
|
||||
ipw.println("Version: " + pi.versionCode);
|
||||
ipw.println("Path: " + pi.applicationInfo.sourceDir);
|
||||
ipw.decreaseIndent();
|
||||
}
|
||||
ipw.decreaseIndent();
|
||||
ipw.println();
|
||||
ipw.println("APEX session state:");
|
||||
ipw.increaseIndent();
|
||||
final ApexSessionInfo[] sessions = mApexService.getSessions();
|
||||
for (ApexSessionInfo si : sessions) {
|
||||
ipw.println("Session ID: " + Integer.toString(si.sessionId));
|
||||
ipw.increaseIndent();
|
||||
if (si.isUnknown) {
|
||||
ipw.println("State: UNKNOWN");
|
||||
} else if (si.isVerified) {
|
||||
ipw.println("State: VERIFIED");
|
||||
} else if (si.isStaged) {
|
||||
ipw.println("State: STAGED");
|
||||
} else if (si.isActivated) {
|
||||
ipw.println("State: ACTIVATED");
|
||||
} else if (si.isActivationPendingRetry) {
|
||||
ipw.println("State: ACTIVATION PENDING RETRY");
|
||||
} else if (si.isActivationFailed) {
|
||||
ipw.println("State: ACTIVATION FAILED");
|
||||
}
|
||||
ipw.decreaseIndent();
|
||||
}
|
||||
ipw.decreaseIndent();
|
||||
} catch (RemoteException e) {
|
||||
ipw.println("Couldn't communicate with apexd.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,7 +186,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
||||
}
|
||||
};
|
||||
|
||||
public PackageInstallerService(Context context, PackageManagerService pm) {
|
||||
public PackageInstallerService(Context context, PackageManagerService pm, ApexManager am) {
|
||||
mContext = context;
|
||||
mPm = pm;
|
||||
mPermissionManager = LocalServices.getService(PermissionManagerInternal.class);
|
||||
@@ -204,7 +204,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
||||
mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions");
|
||||
mSessionsDir.mkdirs();
|
||||
|
||||
mStagingManager = new StagingManager(pm, this);
|
||||
mStagingManager = new StagingManager(pm, this, am);
|
||||
}
|
||||
|
||||
private void setBootCompleted() {
|
||||
|
||||
@@ -119,9 +119,6 @@ import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.apex.ApexInfo;
|
||||
import android.apex.ApexSessionInfo;
|
||||
import android.apex.IApexService;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManagerInternal;
|
||||
import android.app.AppDetailsActivity;
|
||||
@@ -733,10 +730,10 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
@GuardedBy("mPackages")
|
||||
final private ArraySet<PackageListObserver> mPackageListObservers = new ArraySet<>();
|
||||
|
||||
private PackageManager mPackageManager;
|
||||
|
||||
private final ModuleInfoProvider mModuleInfoProvider;
|
||||
|
||||
private final ApexManager mApexManager;
|
||||
|
||||
class PackageParserCallback implements PackageParser.Callback {
|
||||
@Override public final boolean hasFeature(String feature) {
|
||||
return PackageManagerService.this.hasSystemFeature(feature, 0);
|
||||
@@ -3074,7 +3071,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
mInstallerService = new PackageInstallerService(context, this);
|
||||
mApexManager = new ApexManager();
|
||||
mInstallerService = new PackageInstallerService(context, this, mApexManager);
|
||||
final Pair<ComponentName, String> instantAppResolverComponent =
|
||||
getInstantAppResolverLPr();
|
||||
if (instantAppResolverComponent != null) {
|
||||
@@ -3934,27 +3932,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
//
|
||||
if (!matchFactoryOnly && (flags & MATCH_APEX) != 0) {
|
||||
//TODO(b/123052859) Don't do file operations every time there is a query.
|
||||
final IApexService apex = IApexService.Stub.asInterface(
|
||||
ServiceManager.getService("apexservice"));
|
||||
if (apex != null) {
|
||||
try {
|
||||
final ApexInfo activePkg = apex.getActivePackage(packageName);
|
||||
if (activePkg != null && !TextUtils.isEmpty(activePkg.packagePath)) {
|
||||
try {
|
||||
return PackageParser.generatePackageInfoFromApex(
|
||||
new File(activePkg.packagePath), true /* collect certs */);
|
||||
} catch (PackageParserException pe) {
|
||||
Log.e(TAG, "Unable to parse package at "
|
||||
+ activePkg.packagePath, pe);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Unable to retrieve packages from apexservice: " + e.toString());
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Unable to connect to apexservice for querying packages.");
|
||||
}
|
||||
return mApexManager.getActivePackage(packageName);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -7851,25 +7829,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
if (listApex) {
|
||||
// TODO(b/119767311): include uninstalled/inactive APEX if
|
||||
// MATCH_UNINSTALLED_PACKAGES is set.
|
||||
final IApexService apex = IApexService.Stub.asInterface(
|
||||
ServiceManager.getService("apexservice"));
|
||||
if (apex != null) {
|
||||
try {
|
||||
final ApexInfo[] activePkgs = apex.getActivePackages();
|
||||
for (ApexInfo ai : activePkgs) {
|
||||
try {
|
||||
list.add(PackageParser.generatePackageInfoFromApex(
|
||||
new File(ai.packagePath), true /* collect certs */));
|
||||
} catch (PackageParserException pe) {
|
||||
throw new IllegalStateException("Unable to parse: " + ai, pe);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Unable to retrieve packages from apexservice: " + e.toString());
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Unable to connect to apexservice for querying packages.");
|
||||
}
|
||||
list.addAll(mApexManager.getActivePackages());
|
||||
}
|
||||
return new ParceledListSlice<>(list);
|
||||
}
|
||||
@@ -21319,51 +21279,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
|
||||
if (!checkin && dumpState.isDumping(DumpState.DUMP_APEX)) {
|
||||
final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
|
||||
ipw.println();
|
||||
ipw.println("Active APEX packages:");
|
||||
ipw.increaseIndent();
|
||||
final IApexService apex = IApexService.Stub.asInterface(
|
||||
ServiceManager.getService("apexservice"));
|
||||
try {
|
||||
final ApexInfo[] activeApexes = apex.getActivePackages();
|
||||
for (ApexInfo ai : activeApexes) {
|
||||
if (packageName != null && !packageName.equals(ai.packageName)) {
|
||||
continue;
|
||||
}
|
||||
ipw.println(ai.packageName);
|
||||
ipw.increaseIndent();
|
||||
ipw.println("Version: " + Long.toString(ai.versionCode));
|
||||
ipw.println("Path: " + ai.packagePath);
|
||||
ipw.decreaseIndent();
|
||||
}
|
||||
ipw.decreaseIndent();
|
||||
ipw.println();
|
||||
ipw.println("APEX session state:");
|
||||
ipw.increaseIndent();
|
||||
final ApexSessionInfo[] sessions = apex.getSessions();
|
||||
for (ApexSessionInfo si : sessions) {
|
||||
ipw.println("Session ID: " + Integer.toString(si.sessionId));
|
||||
ipw.increaseIndent();
|
||||
if (si.isUnknown) {
|
||||
ipw.println("State: UNKNOWN");
|
||||
} else if (si.isVerified) {
|
||||
ipw.println("State: VERIFIED");
|
||||
} else if (si.isStaged) {
|
||||
ipw.println("State: STAGED");
|
||||
} else if (si.isActivated) {
|
||||
ipw.println("State: ACTIVATED");
|
||||
} else if (si.isActivationPendingRetry) {
|
||||
ipw.println("State: ACTIVATION PENDING RETRY");
|
||||
} else if (si.isActivationFailed) {
|
||||
ipw.println("State: ACTIVATION FAILED");
|
||||
}
|
||||
ipw.decreaseIndent();
|
||||
}
|
||||
ipw.decreaseIndent();
|
||||
} catch (RemoteException e) {
|
||||
ipw.println("Couldn't communicate with apexd.");
|
||||
}
|
||||
mApexManager.dump(pw, packageName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,12 +20,12 @@ import android.annotation.NonNull;
|
||||
import android.apex.ApexInfo;
|
||||
import android.apex.ApexInfoList;
|
||||
import android.apex.ApexSessionInfo;
|
||||
import android.apex.IApexService;
|
||||
import android.content.Context;
|
||||
import android.content.IIntentReceiver;
|
||||
import android.content.IIntentSender;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageInstaller;
|
||||
import android.content.pm.PackageInstaller.SessionInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -41,7 +41,6 @@ import android.os.IBinder;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.apk.ApkSignatureVerifier;
|
||||
@@ -68,14 +67,16 @@ public class StagingManager {
|
||||
|
||||
private final PackageInstallerService mPi;
|
||||
private final PackageManagerService mPm;
|
||||
private final ApexManager mApexManager;
|
||||
private final Handler mBgHandler;
|
||||
|
||||
@GuardedBy("mStagedSessions")
|
||||
private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>();
|
||||
|
||||
StagingManager(PackageManagerService pm, PackageInstallerService pi) {
|
||||
StagingManager(PackageManagerService pm, PackageInstallerService pi, ApexManager am) {
|
||||
mPm = pm;
|
||||
mPi = pi;
|
||||
mApexManager = am;
|
||||
mBgHandler = BackgroundThread.getHandler();
|
||||
}
|
||||
|
||||
@@ -100,7 +101,7 @@ public class StagingManager {
|
||||
return new ParceledListSlice<>(result);
|
||||
}
|
||||
|
||||
private static boolean validateApexSignature(String apexPath, String packageName) {
|
||||
private boolean validateApexSignature(String apexPath, String packageName) {
|
||||
final SigningDetails signingDetails;
|
||||
try {
|
||||
signingDetails = ApkSignatureVerifier.verify(apexPath, SignatureSchemeVersion.JAR);
|
||||
@@ -109,17 +110,9 @@ public class StagingManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
final IApexService apex = IApexService.Stub.asInterface(
|
||||
ServiceManager.getService("apexservice"));
|
||||
final ApexInfo apexInfo;
|
||||
try {
|
||||
apexInfo = apex.getActivePackage(packageName);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(TAG, "Unable to contact APEXD", re);
|
||||
return false;
|
||||
}
|
||||
final PackageInfo packageInfo = mApexManager.getActivePackage(packageName);
|
||||
|
||||
if (apexInfo == null || TextUtils.isEmpty(apexInfo.packageName)) {
|
||||
if (packageInfo == null) {
|
||||
// TODO: What is the right thing to do here ? This implies there's no active package
|
||||
// with the given name. This should never be the case in production (where we only
|
||||
// accept updates to existing APEXes) but may be required for testing.
|
||||
@@ -129,9 +122,10 @@ public class StagingManager {
|
||||
final SigningDetails existingSigningDetails;
|
||||
try {
|
||||
existingSigningDetails = ApkSignatureVerifier.verify(
|
||||
apexInfo.packagePath, SignatureSchemeVersion.JAR);
|
||||
packageInfo.applicationInfo.sourceDir, SignatureSchemeVersion.JAR);
|
||||
} catch (PackageParserException e) {
|
||||
Slog.e(TAG, "Unable to parse APEX package: " + apexInfo.packagePath, e);
|
||||
Slog.e(TAG, "Unable to parse APEX package: "
|
||||
+ packageInfo.applicationInfo.sourceDir, e);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -143,10 +137,10 @@ public class StagingManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean submitSessionToApexService(@NonNull PackageInstallerSession session,
|
||||
List<PackageInstallerSession> childSessions,
|
||||
ApexInfoList apexInfoList) {
|
||||
return sendSubmitStagedSessionRequest(
|
||||
private boolean submitSessionToApexService(@NonNull PackageInstallerSession session,
|
||||
List<PackageInstallerSession> childSessions,
|
||||
ApexInfoList apexInfoList) {
|
||||
return mApexManager.submitStagedSession(
|
||||
session.sessionId,
|
||||
childSessions != null
|
||||
? childSessions.stream().mapToInt(s -> s.sessionId).toArray() :
|
||||
@@ -154,33 +148,6 @@ public class StagingManager {
|
||||
apexInfoList);
|
||||
}
|
||||
|
||||
private static boolean sendSubmitStagedSessionRequest(
|
||||
int sessionId, int[] childSessionIds, ApexInfoList apexInfoList) {
|
||||
final IApexService apex = IApexService.Stub.asInterface(
|
||||
ServiceManager.getService("apexservice"));
|
||||
boolean success;
|
||||
try {
|
||||
success = apex.submitStagedSession(sessionId, childSessionIds, apexInfoList);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(TAG, "Unable to contact apexservice", re);
|
||||
return false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private static boolean sendMarkStagedSessionReadyRequest(int sessionId) {
|
||||
final IApexService apex = IApexService.Stub.asInterface(
|
||||
ServiceManager.getService("apexservice"));
|
||||
boolean success;
|
||||
try {
|
||||
success = apex.markStagedSessionReady(sessionId);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(TAG, "Unable to contact apexservice", re);
|
||||
return false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private static boolean isApexSession(@NonNull PackageInstallerSession session) {
|
||||
return (session.params.installFlags & PackageManager.INSTALL_APEX) != 0;
|
||||
}
|
||||
@@ -260,7 +227,7 @@ public class StagingManager {
|
||||
}
|
||||
|
||||
session.setStagedSessionReady();
|
||||
if (!sendMarkStagedSessionReadyRequest(session.sessionId)) {
|
||||
if (!mApexManager.markStagedSessionReady(session.sessionId)) {
|
||||
session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
|
||||
"APEX staging failed, check logcat messages from apexd for more "
|
||||
+ "details.");
|
||||
@@ -284,16 +251,12 @@ public class StagingManager {
|
||||
|
||||
private void resumeSession(@NonNull PackageInstallerSession session) {
|
||||
if (sessionContainsApex(session)) {
|
||||
// Check with apexservice whether the apex
|
||||
// packages have been activated.
|
||||
final IApexService apex = IApexService.Stub.asInterface(
|
||||
ServiceManager.getService("apexservice"));
|
||||
ApexSessionInfo apexSessionInfo;
|
||||
try {
|
||||
apexSessionInfo = apex.getStagedSessionInfo(session.sessionId);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(TAG, "Unable to contact apexservice", re);
|
||||
// TODO should we retry here? Mark the session as failed?
|
||||
// Check with apexservice whether the apex packages have been activated.
|
||||
ApexSessionInfo apexSessionInfo = mApexManager.getStagedSessionInfo(session.sessionId);
|
||||
if (apexSessionInfo == null) {
|
||||
session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
|
||||
"apexd did not know anything about a staged session supposed to be"
|
||||
+ "activated");
|
||||
return;
|
||||
}
|
||||
if (apexSessionInfo.isActivationFailed || apexSessionInfo.isUnknown) {
|
||||
@@ -323,8 +286,8 @@ public class StagingManager {
|
||||
// The APEX part of the session is activated, proceed with the installation of APKs.
|
||||
if (!installApksInSession(session)) {
|
||||
session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
|
||||
"APEX activation failed. Check logcat messages from apexd for "
|
||||
+ "more information.");
|
||||
"Staged installation of APKs failed. Check logcat messages for"
|
||||
+ "more information.");
|
||||
return;
|
||||
}
|
||||
session.setStagedSessionApplied();
|
||||
|
||||
Reference in New Issue
Block a user