Merge "Give secondary users read-only physical cards." into mnc-dev

This commit is contained in:
Jeff Sharkey
2015-07-29 01:19:43 +00:00
committed by Android (Google) Code Review
5 changed files with 52 additions and 17 deletions

View File

@@ -80,7 +80,8 @@ public class Environment {
}
public File[] getExternalDirs() {
final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId);
final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId,
StorageManager.FLAG_FOR_WRITE);
final File[] files = new File[volumes.length];
for (int i = 0; i < volumes.length; i++) {
files[i] = volumes[i].getPathFile();

View File

@@ -758,7 +758,7 @@ public interface IMountService extends IInterface {
return _result;
}
public StorageVolume[] getVolumeList(int uid, String packageName)
public StorageVolume[] getVolumeList(int uid, String packageName, int flags)
throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
@@ -767,6 +767,7 @@ public interface IMountService extends IInterface {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(uid);
_data.writeString(packageName);
_data.writeInt(flags);
mRemote.transact(Stub.TRANSACTION_getVolumeList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArray(StorageVolume.CREATOR);
@@ -1609,7 +1610,8 @@ public interface IMountService extends IInterface {
data.enforceInterface(DESCRIPTOR);
int uid = data.readInt();
String packageName = data.readString();
StorageVolume[] result = getVolumeList(uid, packageName);
int _flags = data.readInt();
StorageVolume[] result = getVolumeList(uid, packageName, _flags);
reply.writeNoException();
reply.writeTypedArray(result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
return true;
@@ -2059,7 +2061,7 @@ public interface IMountService extends IInterface {
/**
* Returns list of all mountable volumes.
*/
public StorageVolume[] getVolumeList(int uid, String packageName) throws RemoteException;
public StorageVolume[] getVolumeList(int uid, String packageName, int flags) throws RemoteException;
/**
* Gets the path on the filesystem for the ASEC container itself.

View File

@@ -86,6 +86,9 @@ public class StorageManager {
/** {@hide} */
public static final int DEBUG_FORCE_ADOPTABLE = 1 << 0;
/** {@hide} */
public static final int FLAG_FOR_WRITE = 1 << 0;
private final Context mContext;
private final ContentResolver mResolver;
@@ -812,7 +815,7 @@ public class StorageManager {
/** {@hide} */
public static @Nullable StorageVolume getStorageVolume(File file, int userId) {
return getStorageVolume(getVolumeList(userId), file);
return getStorageVolume(getVolumeList(userId, 0), file);
}
/** {@hide} */
@@ -852,11 +855,11 @@ public class StorageManager {
/** {@hide} */
public @NonNull StorageVolume[] getVolumeList() {
return getVolumeList(mContext.getUserId());
return getVolumeList(mContext.getUserId(), 0);
}
/** {@hide} */
public static @NonNull StorageVolume[] getVolumeList(int userId) {
public static @NonNull StorageVolume[] getVolumeList(int userId, int flags) {
final IMountService mountService = IMountService.Stub.asInterface(
ServiceManager.getService("mount"));
try {
@@ -877,7 +880,7 @@ public class StorageManager {
if (uid <= 0) {
return new StorageVolume[0];
}
return mountService.getVolumeList(uid, packageName);
return mountService.getVolumeList(uid, packageName, flags);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}

View File

@@ -46,6 +46,19 @@ import java.util.Objects;
* Information about a storage volume that may be mounted. A volume may be a
* partition on a physical {@link DiskInfo}, an emulated volume above some other
* storage medium, or a standalone container like an ASEC or OBB.
* <p>
* Volumes may be mounted with various flags:
* <ul>
* <li>{@link #MOUNT_FLAG_PRIMARY} means the volume provides primary external
* storage, historically found at {@code /sdcard}.
* <li>{@link #MOUNT_FLAG_VISIBLE} means the volume is visible to third-party
* apps for direct filesystem access. The system should send out relevant
* storage broadcasts and index any media on visible volumes. Visible volumes
* are considered a more stable part of the device, which is why we take the
* time to index them. In particular, transient volumes like USB OTG devices
* <em>should not</em> be marked as visible; their contents should be surfaced
* to apps through the Storage Access Framework.
* </ul>
*
* @hide
*/
@@ -255,8 +268,23 @@ public class VolumeInfo implements Parcelable {
return (mountFlags & MOUNT_FLAG_VISIBLE) != 0;
}
public boolean isVisibleToUser(int userId) {
if (type == TYPE_PUBLIC && userId == this.mountUserId) {
public boolean isVisibleForRead(int userId) {
if (type == TYPE_PUBLIC) {
if (isPrimary() && mountUserId != userId) {
// Primary physical is only visible to single user
return false;
} else {
return isVisible();
}
} else if (type == TYPE_EMULATED) {
return isVisible();
} else {
return false;
}
}
public boolean isVisibleForWrite(int userId) {
if (type == TYPE_PUBLIC && mountUserId == userId) {
return isVisible();
} else if (type == TYPE_EMULATED) {
return isVisible();
@@ -276,7 +304,7 @@ public class VolumeInfo implements Parcelable {
public File getPathForUser(int userId) {
if (path == null) {
return null;
} else if (type == TYPE_PUBLIC && userId == this.mountUserId) {
} else if (type == TYPE_PUBLIC) {
return new File(path);
} else if (type == TYPE_EMULATED) {
return new File(path, Integer.toString(userId));
@@ -306,6 +334,7 @@ public class VolumeInfo implements Parcelable {
final boolean allowMassStorage = false;
final String envState = reportUnmounted
? Environment.MEDIA_UNMOUNTED : getEnvironmentForState(state);
File userPath = getPathForUser(userId);
if (userPath == null) {
userPath = new File("/dev/null");

View File

@@ -69,7 +69,6 @@ import android.os.storage.IMountServiceListener;
import android.os.storage.IMountShutdownObserver;
import android.os.storage.IObbActionListener;
import android.os.storage.MountServiceInternal;
import android.os.storage.MountServiceInternal.ExternalStorageMountPolicy;
import android.os.storage.OnObbStateChangeListener;
import android.os.storage.StorageManager;
import android.os.storage.StorageResultCode;
@@ -809,7 +808,7 @@ class MountService extends IMountService.Stub
synchronized (mVolumes) {
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
if (vol.isVisibleToUser(userId) && vol.isMountedReadable()) {
if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
@@ -1252,7 +1251,7 @@ class MountService extends IMountService.Stub
// started after this point will trigger additional
// user-specific broadcasts.
for (int userId : mStartedUsers) {
if (vol.isVisibleToUser(userId)) {
if (vol.isVisibleForRead(userId)) {
final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
@@ -2610,13 +2609,14 @@ class MountService extends IMountService.Stub
}
@Override
public StorageVolume[] getVolumeList(int uid, String packageName) {
public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
final ArrayList<StorageVolume> res = new ArrayList<>();
boolean foundPrimary = false;
final int userId = UserHandle.getUserId(uid);
final boolean reportUnmounted;
final long identity = Binder.clearCallingIdentity();
try {
reportUnmounted = !mMountServiceInternal.hasExternalStorage(
@@ -2628,7 +2628,7 @@ class MountService extends IMountService.Stub
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
if (vol.isVisibleToUser(userId)) {
if (forWrite ? vol.isVisibleForWrite(userId) : vol.isVisibleForRead(userId)) {
final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
reportUnmounted);
if (vol.isPrimary()) {