am d2c41457: Merge "Let\'s reinvent storage, yet again!" into mnc-dev

* commit 'd2c414573242fc59a2d34f66f1dfb610ec7d59a3':
  Let's reinvent storage, yet again!
This commit is contained in:
Jeff Sharkey
2015-06-26 15:52:51 +00:00
committed by Android Git Automerger
11 changed files with 178 additions and 62 deletions

View File

@ -504,4 +504,5 @@ interface IPackageManager {
void grantDefaultPermissions(int userId);
void setCarrierAppPackagesProvider(in IPackagesProvider provider);
int getMountExternalMode(int uid);
}

View File

@ -643,6 +643,10 @@ public class Process {
}
if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
argsForZygote.add("--mount-external-default");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
argsForZygote.add("--mount-external-read");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
argsForZygote.add("--mount-external-write");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
@ -802,7 +806,12 @@ public class Process {
* @hide
*/
public static final boolean isIsolated() {
int uid = UserHandle.getAppId(myUid());
return isIsolated(myUid());
}
/** {@hide} */
public static final boolean isIsolated(int uid) {
uid = UserHandle.getAppId(uid);
return uid >= FIRST_ISOLATED_UID && uid <= LAST_ISOLATED_UID;
}

View File

@ -1177,6 +1177,21 @@ public interface IMountService extends IInterface {
_data.recycle();
}
}
@Override
public void remountUid(int uid) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(uid);
mRemote.transact(Stub.TRANSACTION_remountUid, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
private static final String DESCRIPTOR = "IMountService";
@ -1292,6 +1307,8 @@ public interface IMountService extends IInterface {
static final int TRANSACTION_benchmark = IBinder.FIRST_CALL_TRANSACTION + 59;
static final int TRANSACTION_setDebugFlags = IBinder.FIRST_CALL_TRANSACTION + 60;
static final int TRANSACTION_remountUid = IBinder.FIRST_CALL_TRANSACTION + 61;
/**
* Cast an IBinder object into an IMountService interface, generating a
* proxy if needed.
@ -1845,6 +1862,13 @@ public interface IMountService extends IInterface {
reply.writeNoException();
return true;
}
case TRANSACTION_remountUid: {
data.enforceInterface(DESCRIPTOR);
int uid = data.readInt();
remountUid(uid);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
@ -2154,4 +2178,6 @@ public interface IMountService extends IInterface {
public String getPrimaryStorageUuid() throws RemoteException;
public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback)
throws RemoteException;
public void remountUid(int uid) throws RemoteException;
}

View File

@ -870,6 +870,15 @@ public class StorageManager {
throw new IllegalStateException("Missing primary storage");
}
/** {@hide} */
public void remountUid(int uid) {
try {
mMountService.remountUid(uid);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
/** {@hide} */
private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES;

View File

@ -46,8 +46,12 @@ public final class Zygote {
/** No external storage should be mounted. */
public static final int MOUNT_EXTERNAL_NONE = 0;
/** Default user-specific external storage should be mounted. */
/** Default external storage should be mounted. */
public static final int MOUNT_EXTERNAL_DEFAULT = 1;
/** Read-only external storage should be mounted. */
public static final int MOUNT_EXTERNAL_READ = 2;
/** Read-write external storage should be mounted. */
public static final int MOUNT_EXTERNAL_WRITE = 3;
private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();

View File

@ -519,6 +519,10 @@ class ZygoteConnection {
niceName = arg.substring(arg.indexOf('=') + 1);
} else if (arg.equals("--mount-external-default")) {
mountExternal = Zygote.MOUNT_EXTERNAL_DEFAULT;
} else if (arg.equals("--mount-external-read")) {
mountExternal = Zygote.MOUNT_EXTERNAL_READ;
} else if (arg.equals("--mount-external-write")) {
mountExternal = Zygote.MOUNT_EXTERNAL_WRITE;
} else if (arg.equals("--query-abi-list")) {
abiListQuery = true;
} else if (arg.startsWith("--instruction-set=")) {

View File

@ -66,6 +66,8 @@ static jmethodID gCallPostForkChildHooks;
enum MountExternalKind {
MOUNT_EXTERNAL_NONE = 0,
MOUNT_EXTERNAL_DEFAULT = 1,
MOUNT_EXTERNAL_READ = 2,
MOUNT_EXTERNAL_WRITE = 3,
};
static void RuntimeAbort(JNIEnv* env) {
@ -249,38 +251,49 @@ static void SetSchedulerPolicy(JNIEnv* env) {
// Create a private mount namespace and bind mount appropriate emulated
// storage for the given user.
static bool MountEmulatedStorage(uid_t uid, jint mount_mode, bool force_mount_namespace) {
if (mount_mode == MOUNT_EXTERNAL_NONE && !force_mount_namespace) {
static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
bool force_mount_namespace) {
// See storage config details at http://source.android.com/tech/storage/
// Create a second private mount namespace for our process
if (unshare(CLONE_NEWNS) == -1) {
ALOGW("Failed to unshare(): %s", strerror(errno));
return false;
}
// Unmount storage provided by root namespace and mount requested view
umount2("/storage", MNT_FORCE);
String8 storageSource;
if (mount_mode == MOUNT_EXTERNAL_DEFAULT) {
storageSource = "/mnt/runtime_default";
} else if (mount_mode == MOUNT_EXTERNAL_READ) {
storageSource = "/mnt/runtime_read";
} else if (mount_mode == MOUNT_EXTERNAL_WRITE) {
storageSource = "/mnt/runtime_write";
} else {
// Sane default of no storage visible
return true;
}
if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
ALOGW("Failed to mount %s to /storage: %s", storageSource.string(), strerror(errno));
return false;
}
// Mount user-specific symlink helpers into place
userid_t user_id = multiuser_get_user_id(uid);
const String8 userSource(String8::format("/mnt/user/%d", user_id));
if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
return false;
}
if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self",
NULL, MS_BIND, NULL)) == -1) {
ALOGW("Failed to mount %s to /storage/self: %s", userSource.string(), strerror(errno));
return false;
}
return true;
}
// Create a second private mount namespace for our process
if (unshare(CLONE_NEWNS) == -1) {
ALOGW("Failed to unshare(): %s", strerror(errno));
return false;
}
if (mount_mode == MOUNT_EXTERNAL_NONE) {
return true;
}
// See storage config details at http://source.android.com/tech/storage/
userid_t user_id = multiuser_get_user_id(uid);
// Bind mount user-specific storage into place
const String8 source(String8::format("/mnt/user/%d", user_id));
const String8 target(String8::format("/storage/self"));
if (fs_prepare_dir(source.string(), 0755, 0, 0) == -1) {
return false;
}
if (TEMP_FAILURE_RETRY(mount(source.string(), target.string(), NULL, MS_BIND, NULL)) == -1) {
ALOGW("Failed to mount %s to %s: %s", source.string(), target.string(), strerror(errno));
return false;
}
return true;
}
static bool NeedsNoRandomizeWorkaround() {
@ -543,7 +556,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer(
pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
debug_flags, rlimits,
permittedCapabilities, effectiveCapabilities,
MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL,
MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
NULL, NULL);
if (pid > 0) {
// The zygote process checks whether the child process has died or not.

View File

@ -58,21 +58,6 @@
<group gid="log" />
</permission>
<permission name="android.permission.READ_EXTERNAL_STORAGE" perUser="true" >
<group gid="sdcard_r" />
</permission>
<permission name="android.permission.WRITE_EXTERNAL_STORAGE" perUser="true" >
<group gid="sdcard_r" />
<group gid="sdcard_rw" />
</permission>
<permission name="android.permission.ACCESS_ALL_EXTERNAL_STORAGE" >
<group gid="sdcard_r" />
<group gid="sdcard_rw" />
<group gid="sdcard_all" />
</permission>
<permission name="android.permission.WRITE_MEDIA_STORAGE" >
<group gid="media_rw" />
</permission>

View File

@ -50,7 +50,9 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
@ -84,6 +86,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
@ -675,13 +678,15 @@ class MountService extends IMountService.Stub
}
private void handleSystemReady() {
resetIfReadyAndConnected();
synchronized (mLock) {
resetIfReadyAndConnectedLocked();
}
// Start scheduling nominally-daily fstrim operations
MountServiceIdler.scheduleIdlePass(mContext);
}
private void resetIfReadyAndConnected() {
private void resetIfReadyAndConnectedLocked() {
Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
+ ", mDaemonConnected=" + mDaemonConnected);
if (mSystemReady && mDaemonConnected) {
@ -780,7 +785,9 @@ class MountService extends IMountService.Stub
}
private void handleDaemonConnected() {
resetIfReadyAndConnected();
synchronized (mLock) {
resetIfReadyAndConnectedLocked();
}
/*
* Now that we've done our initialization, release
@ -1600,7 +1607,7 @@ class MountService extends IMountService.Stub
// reset vold so we bind into new volume into place.
if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
resetIfReadyAndConnected();
resetIfReadyAndConnectedLocked();
}
writeSettingsLocked();
@ -1628,7 +1635,7 @@ class MountService extends IMountService.Stub
}
writeSettingsLocked();
resetIfReadyAndConnected();
resetIfReadyAndConnectedLocked();
}
}
@ -1640,6 +1647,30 @@ class MountService extends IMountService.Stub
}
}
@Override
public void remountUid(int uid) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
waitForReady();
final int mountExternal = mPms.getMountExternalMode(uid);
final String mode;
if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
mode = "default";
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
mode = "read";
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
mode = "write";
} else {
mode = "none";
}
try {
mConnector.execute("volume", "remount_uid", uid, mode);
} catch (NativeDaemonConnectorException e) {
Slog.w(TAG, "Failed to remount UID " + uid + " as " + mode + ": " + e);
}
}
@Override
public void setDebugFlags(int flags, int mask) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
@ -1651,7 +1682,7 @@ class MountService extends IMountService.Stub
}
writeSettingsLocked();
resetIfReadyAndConnected();
resetIfReadyAndConnectedLocked();
}
}
@ -1688,7 +1719,7 @@ class MountService extends IMountService.Stub
Slog.d(TAG, "Skipping move to/from primary physical");
onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
resetIfReadyAndConnected();
resetIfReadyAndConnectedLocked();
} else {
final VolumeInfo from = Preconditions.checkNotNull(
@ -2022,7 +2053,7 @@ class MountService extends IMountService.Stub
@Override
public void finishMediaUpdate() {
if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("no permission to call finishMediaUpdate()");
}
if (mUnmountSignal != null) {

View File

@ -18,7 +18,9 @@ package com.android.server.am;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
@ -3209,13 +3211,14 @@ public final class ActivityManagerService extends ActivityManagerNative
int uid = app.uid;
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_DEFAULT;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
checkTime(startTime, "startProcess: getting gids from package manager");
permGids = AppGlobals.getPackageManager().getPackageGids(app.info.packageName,
app.userId);
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName, app.userId);
mountExternal = pm.getMountExternalMode(uid);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}

View File

@ -18,6 +18,7 @@ package com.android.server.pm;
import static android.Manifest.permission.GRANT_REVOKE_PERMISSIONS;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
@ -54,6 +55,7 @@ import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST;
import static android.content.pm.PackageManager.MOVE_FAILED_INTERNAL_ERROR;
import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING;
import static android.content.pm.PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.PackageParser.isApkFile;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
@ -196,6 +198,7 @@ import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
import com.android.internal.os.IParcelFileDescriptorFactory;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
@ -208,8 +211,8 @@ import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
import com.android.server.Watchdog;
import com.android.server.pm.Settings.DatabaseVersion;
import com.android.server.pm.PermissionsState.PermissionState;
import com.android.server.pm.Settings.DatabaseVersion;
import com.android.server.storage.DeviceStorageMonitorInternal;
import org.xmlpull.v1.XmlPullParser;
@ -2562,6 +2565,21 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
@Override
public int getMountExternalMode(int uid) {
if (Process.isIsolated(uid)) {
return Zygote.MOUNT_EXTERNAL_NONE;
} else {
if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_GRANTED) {
return Zygote.MOUNT_EXTERNAL_WRITE;
} else if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_GRANTED) {
return Zygote.MOUNT_EXTERNAL_READ;
} else {
return Zygote.MOUNT_EXTERNAL_DEFAULT;
}
}
}
static PermissionInfo generatePermissionInfo(
BasePermission bp, int flags) {
if (bp.perm != null) {
@ -3201,6 +3219,7 @@ public class PackageManagerService extends IPackageManager.Stub {
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
"grantRuntimePermission");
final int uid;
final SettingBase sb;
synchronized (mPackages) {
@ -3216,6 +3235,7 @@ public class PackageManagerService extends IPackageManager.Stub {
enforceDeclaredAsUsedAndRuntimePermission(pkg, bp);
uid = pkg.applicationInfo.uid;
sb = (SettingBase) pkg.mExtras;
if (sb == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
@ -3245,11 +3265,22 @@ public class PackageManagerService extends IPackageManager.Stub {
} break;
}
mOnPermissionChangeListeners.onPermissionsChanged(pkg.applicationInfo.uid);
mOnPermissionChangeListeners.onPermissionsChanged(uid);
// Not critical if that is lost - app has to request again.
mSettings.writeRuntimePermissionsForUserLPr(userId, false);
}
if (READ_EXTERNAL_STORAGE.equals(name)
|| WRITE_EXTERNAL_STORAGE.equals(name)) {
final long token = Binder.clearCallingIdentity();
try {
final StorageManager storage = mContext.getSystemService(StorageManager.class);
storage.remountUid(uid);
} finally {
Binder.restoreCallingIdentity(token);
}
}
}
@Override