Merge "Give secondary users read-only physical cards." into mnc-dev
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
Reference in New Issue
Block a user