Merge "Add RollbackManagerInternal (4/n)"

This commit is contained in:
JW Wang
2020-05-26 03:07:38 +00:00
committed by Android (Google) Code Review
7 changed files with 143 additions and 49 deletions

View File

@@ -24,6 +24,8 @@ import android.annotation.UserIdInt;
import android.compat.annotation.UnsupportedAppUsage;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
* Representation of a user on the device.
@@ -256,6 +258,26 @@ public final class UserHandle implements Parcelable {
return getAppId(Binder.getCallingUid());
}
/** @hide */
@NonNull
public static int[] fromUserHandles(@NonNull List<UserHandle> users) {
int[] userIds = new int[users.size()];
for (int i = 0; i < userIds.length; ++i) {
userIds[i] = users.get(i).getIdentifier();
}
return userIds;
}
/** @hide */
@NonNull
public static List<UserHandle> toUserHandles(@NonNull int[] userIds) {
List<UserHandle> users = new ArrayList<>(userIds.length);
for (int i = 0; i < userIds.length; ++i) {
users.add(UserHandle.of(userIds[i]));
}
return users;
}
/** @hide */
@TestApi
@SystemApi

View File

@@ -236,7 +236,6 @@ import android.content.pm.parsing.component.ParsedService;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.content.res.Resources;
import android.content.rollback.IRollbackManager;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.hardware.display.DisplayManager;
@@ -367,6 +366,7 @@ import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.permission.PermissionsState;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.rollback.RollbackManagerInternal;
import com.android.server.security.VerityUtils;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.utils.TimingsTraceAndSlog;
@@ -14314,8 +14314,7 @@ public class PackageManagerService extends IPackageManager.Stub
*/
private boolean performRollbackManagerRestore(int userId, int token, PackageInstalledInfo res,
PostInstallData data) {
IRollbackManager rm = IRollbackManager.Stub.asInterface(
ServiceManager.getService(Context.ROLLBACK_SERVICE));
RollbackManagerInternal rm = LocalServices.getService(RollbackManagerInternal.class);
final String packageName = res.pkg.getPackageName();
final int[] allUsers = mUserManager.getUserIds();
@@ -14343,9 +14342,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (ps != null && doSnapshotOrRestore) {
final String seInfo = AndroidPackageUtils.getSeInfo(res.pkg, ps);
try {
rm.snapshotAndRestoreUserData(packageName, installedUsers, appId, ceDataInode,
seInfo, token);
} catch (RemoteException re) {
rm.snapshotAndRestoreUserData(packageName, UserHandle.toUserHandles(installedUsers),
appId, ceDataInode, seInfo, token);
} catch (RuntimeException re) {
Log.e(TAG, "Error snapshotting/restoring user data: " + re);
return false;
}
@@ -21390,7 +21389,7 @@ public class PackageManagerService extends IPackageManager.Stub
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
(new PackageManagerShellCommand(this, mPermissionManagerService)).exec(
(new PackageManagerShellCommand(this, mPermissionManagerService, mContext)).exec(
this, in, out, err, args, callback, resultReceiver);
}

View File

@@ -66,7 +66,6 @@ import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.content.rollback.IRollbackManager;
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
@@ -145,6 +144,7 @@ class PackageManagerShellCommand extends ShellCommand {
final IPackageManager mInterface;
final IPermissionManager mPermissionManager;
final Context mShellPackageContext;
final private WeakHashMap<String, Resources> mResourceCache =
new WeakHashMap<String, Resources>();
int mTargetUser;
@@ -153,9 +153,15 @@ class PackageManagerShellCommand extends ShellCommand {
int mQueryFlags;
PackageManagerShellCommand(
PackageManagerService service, IPermissionManager permissionManager) {
PackageManagerService service, IPermissionManager permissionManager, Context context) {
mInterface = service;
mPermissionManager = permissionManager;
try {
mShellPackageContext = context.createPackageContext("com.android.shell", 0);
} catch (NameNotFoundException e) {
// should not happen
throw new RuntimeException(e);
}
}
@Override
@@ -460,32 +466,25 @@ class PackageManagerShellCommand extends ShellCommand {
}
final LocalIntentReceiver receiver = new LocalIntentReceiver();
try {
IRollbackManager rm = IRollbackManager.Stub.asInterface(
ServiceManager.getService(Context.ROLLBACK_SERVICE));
RollbackInfo rollback = null;
for (RollbackInfo r : (List<RollbackInfo>) rm.getAvailableRollbacks().getList()) {
for (PackageRollbackInfo info : r.getPackages()) {
if (packageName.equals(info.getPackageName())) {
rollback = r;
break;
}
RollbackManager rm = mShellPackageContext.getSystemService(RollbackManager.class);
RollbackInfo rollback = null;
for (RollbackInfo r : rm.getAvailableRollbacks()) {
for (PackageRollbackInfo info : r.getPackages()) {
if (packageName.equals(info.getPackageName())) {
rollback = r;
break;
}
}
if (rollback == null) {
pw.println("No available rollbacks for: " + packageName);
return 1;
}
rm.commitRollback(rollback.getRollbackId(),
ParceledListSlice.<VersionedPackage>emptyList(),
"com.android.shell", receiver.getIntentSender());
} catch (RemoteException re) {
// Cannot happen.
}
if (rollback == null) {
pw.println("No available rollbacks for: " + packageName);
return 1;
}
rm.commitRollback(rollback.getRollbackId(),
Collections.emptyList(), receiver.getIntentSender());
final Intent result = receiver.getResult();
final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
RollbackManager.STATUS_FAILURE);

View File

@@ -40,7 +40,6 @@ import android.content.pm.PackageParser.SigningDetails;
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
import android.content.pm.ParceledListSlice;
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
import android.content.rollback.IRollbackManager;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.os.Bundle;
@@ -52,7 +51,6 @@ import android.os.ParcelFileDescriptor;
import android.os.ParcelableException;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.os.storage.IStorageManager;
@@ -75,6 +73,7 @@ import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.rollback.RollbackManagerInternal;
import com.android.server.rollback.WatchdogRollbackLogger;
import java.io.File;
@@ -483,8 +482,7 @@ public class StagingManager {
final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);
final int[] allUsers = um.getUserIds();
IRollbackManager rm = IRollbackManager.Stub.asInterface(
ServiceManager.getService(Context.ROLLBACK_SERVICE));
RollbackManagerInternal rm = LocalServices.getService(RollbackManagerInternal.class);
for (int i = 0, sessionsSize = apexSessions.size(); i < sessionsSize; i++) {
final String packageName = apexSessions.get(i).getPackageName();
@@ -500,18 +498,18 @@ public class StagingManager {
}
private void snapshotAndRestoreApexUserData(
String packageName, int[] allUsers, IRollbackManager rm) {
String packageName, int[] allUsers, RollbackManagerInternal rm) {
try {
// appId, ceDataInode, and seInfo are not needed for APEXes
rm.snapshotAndRestoreUserData(packageName, allUsers, 0, 0,
rm.snapshotAndRestoreUserData(packageName, UserHandle.toUserHandles(allUsers), 0, 0,
null, 0 /*token*/);
} catch (RemoteException re) {
} catch (RuntimeException re) {
Slog.e(TAG, "Error snapshotting/restoring user data: " + re);
}
}
private void snapshotAndRestoreApkInApexUserData(
String packageName, int[] allUsers, IRollbackManager rm) {
String packageName, int[] allUsers, RollbackManagerInternal rm) {
PackageManagerInternal mPmi = LocalServices.getService(PackageManagerInternal.class);
AndroidPackage pkg = mPmi.getPackage(packageName);
if (pkg == null) {
@@ -532,9 +530,9 @@ public class StagingManager {
final String seInfo = AndroidPackageUtils.getSeInfo(pkg, ps);
try {
rm.snapshotAndRestoreUserData(packageName, installedUsers, appId, ceDataInode,
seInfo, 0 /*token*/);
} catch (RemoteException re) {
rm.snapshotAndRestoreUserData(packageName, UserHandle.toUserHandles(installedUsers),
appId, ceDataInode, seInfo, 0 /*token*/);
} catch (RuntimeException re) {
Slog.e(TAG, "Error snapshotting/restoring user data: " + re);
}
}
@@ -878,11 +876,11 @@ public class StagingManager {
if ((apksToInstall.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
// If rollback is available for this session, notify the rollback
// manager of the apk session so it can properly enable rollback.
final IRollbackManager rm = IRollbackManager.Stub.asInterface(
ServiceManager.getService(Context.ROLLBACK_SERVICE));
final RollbackManagerInternal rm =
LocalServices.getService(RollbackManagerInternal.class);
try {
rm.notifyStagedApkSession(session.sessionId, apksToInstall.sessionId);
} catch (RemoteException re) {
} catch (RuntimeException re) {
Slog.e(TAG, "Failed to notifyStagedApkSession for session: "
+ session.sessionId, re);
}
@@ -1384,8 +1382,8 @@ public class StagingManager {
// If rollback is enabled for this session, we call through to the RollbackManager
// with the list of sessions it must enable rollback for. Note that
// notifyStagedSession is a synchronous operation.
final IRollbackManager rm = IRollbackManager.Stub.asInterface(
ServiceManager.getService(Context.ROLLBACK_SERVICE));
final RollbackManagerInternal rm =
LocalServices.getService(RollbackManagerInternal.class);
try {
// NOTE: To stay consistent with the non-staged install flow, we don't fail the
// entire install if rollbacks can't be enabled.
@@ -1395,7 +1393,7 @@ public class StagingManager {
mSessionRollbackIds.put(session.sessionId, rollbackId);
}
}
} catch (RemoteException re) {
} catch (RuntimeException re) {
Slog.e(TAG, "Failed to notifyStagedSession for session: "
+ session.sessionId, re);
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2020 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.
*/
package com.android.server.rollback;
import android.annotation.NonNull;
import android.os.UserHandle;
import java.util.List;
/**
* A partial interface of IRollbackManager used by the system server only.
*
* @hide
*/
public interface RollbackManagerInternal {
/**
* Exposed for use from the system server only. Callback from the package
* manager during the install flow when user data can be backed up and restored for a given
* package.
*
* @param packageName Name of the package to restore/backup user data for
* @param users Users whose data to be restored/backed up
* @param appId ID of the package to restore/backup user data for
* @param ceDataInode The index node of CE data to restore/backup
* @param seInfo The seinfo tag used by SELinux policy
* @param token Used to inform the package manager that the pending package install is finished
*/
void snapshotAndRestoreUserData(@NonNull String packageName, @NonNull List<UserHandle> users,
int appId, long ceDataInode, @NonNull String seInfo, int token);
/**
* Used by the staging manager to notify the RollbackManager that a session is
* being staged. In the case of multi-package sessions, the specified sessionId
* is that of the parent session.
*
* NOTE: This call is synchronous.
*
* @param sessionId The session ID that is being staged
* @return The rollback id if rollback was enabled successfully, or -1 if not.
*/
int notifyStagedSession(int sessionId);
/**
* Used by the staging manager to notify the RollbackManager of the apk
* session for a staged session.
*
* @param originalSessionId The original session ID where this apk session belongs
* @param apkSessionId The ID of this apk session
*/
void notifyStagedApkSession(int originalSessionId, int apkSessionId);
}

View File

@@ -18,6 +18,7 @@ package com.android.server.rollback;
import android.content.Context;
import com.android.server.LocalServices;
import com.android.server.SystemService;
/**
@@ -38,6 +39,7 @@ public final class RollbackManagerService extends SystemService {
public void onStart() {
mService = new RollbackManagerServiceImpl(getContext());
publishBinderService(Context.ROLLBACK_SERVICE, mService);
LocalServices.addService(RollbackManagerInternal.class, mService);
}
@Override

View File

@@ -118,7 +118,7 @@ import java.util.function.Supplier;
* mutually-exclusive to ensure @WorkerThread methods and @ExtThread ones never call into each
* other.
*/
class RollbackManagerServiceImpl extends IRollbackManager.Stub {
class RollbackManagerServiceImpl extends IRollbackManager.Stub implements RollbackManagerInternal {
/**
* Denotes that the annotated methods is intended for external entities and should be called on
* an external thread. By 'external' we mean any thread that is not the handler thread.
@@ -925,6 +925,15 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
appInfo.splitSourceDirs, rollbackDataPolicy);
}
@ExtThread
@Override
public void snapshotAndRestoreUserData(String packageName, List<UserHandle> users, int appId,
long ceDataInode, String seInfo, int token) {
assertNotInWorkerThread();
snapshotAndRestoreUserData(packageName, UserHandle.fromUserHandles(users), appId,
ceDataInode, seInfo, token);
}
@ExtThread
@Override
public void snapshotAndRestoreUserData(String packageName, int[] userIds, int appId,