diff options
author | Svet Ganov <svetoslavganov@google.com> | 2015-07-14 01:24:34 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-07-14 01:24:37 +0000 |
commit | 8cee6587e0efb2d8e63f1505b057a1e328525017 (patch) | |
tree | 18030af7a69474b903bfdd2b7705ad06e4a8dc4e /services | |
parent | 4b9b3e4731ffb962daf0f5029450001a8a6e7c00 (diff) | |
parent | 6ee871e59812fea4525c50231f677c4bd10c74b8 (diff) | |
download | frameworks_base-8cee6587e0efb2d8e63f1505b057a1e328525017.zip frameworks_base-8cee6587e0efb2d8e63f1505b057a1e328525017.tar.gz frameworks_base-8cee6587e0efb2d8e63f1505b057a1e328525017.tar.bz2 |
Merge "Teach storage appops." into mnc-dev
Diffstat (limited to 'services')
4 files changed, 149 insertions, 49 deletions
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index f0fc399..417f18d 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -48,6 +48,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; +import android.os.storage.MountServiceInternal; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; @@ -60,6 +61,7 @@ import android.util.Xml; import com.android.internal.app.IAppOpsService; import com.android.internal.app.IAppOpsCallback; +import com.android.internal.os.Zygote; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.XmlUtils; @@ -245,6 +247,34 @@ public class AppOpsService extends IAppOpsService.Stub { scheduleFastWriteLocked(); } } + + MountServiceInternal mountServiceInternal = LocalServices.getService( + MountServiceInternal.class); + mountServiceInternal.addExternalStoragePolicy( + new MountServiceInternal.ExternalStorageMountPolicy() { + @Override + public int getMountMode(int uid, String packageName) { + if (Process.isIsolated(uid)) { + return Zygote.MOUNT_EXTERNAL_NONE; + } + if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid, + packageName) != AppOpsManager.MODE_ALLOWED) { + return Zygote.MOUNT_EXTERNAL_NONE; + } + if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid, + packageName) != AppOpsManager.MODE_ALLOWED) { + return Zygote.MOUNT_EXTERNAL_READ; + } + return Zygote.MOUNT_EXTERNAL_WRITE; + } + + @Override + public boolean hasExternalStorage(int uid, String packageName) { + final int mountMode = getMountMode(uid, packageName); + return mountMode == Zygote.MOUNT_EXTERNAL_READ + || mountMode == Zygote.MOUNT_EXTERNAL_WRITE; + } + }); } public void packageRemoved(int uid, String packageName) { diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index da552dd..bc61c3d 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -68,6 +68,8 @@ import android.os.storage.IMountService; 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; @@ -127,6 +129,7 @@ import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -307,16 +310,6 @@ class MountService extends IMountService.Stub @GuardedBy("mLock") private String mMoveTargetUuid; - private DiskInfo findDiskById(String id) { - synchronized (mLock) { - final DiskInfo disk = mDisks.get(id); - if (disk != null) { - return disk; - } - } - throw new IllegalArgumentException("No disk found for ID " + id); - } - private VolumeInfo findVolumeByIdOrThrow(String id) { synchronized (mLock) { final VolumeInfo vol = mVolumes.get(id); @@ -456,6 +449,9 @@ class MountService extends IMountService.Stub /** Map from raw paths to {@link ObbState}. */ final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>(); + // Not guarded by a lock. + private final MountServiceInternalImpl mMountServiceInternal = new MountServiceInternalImpl(); + class ObbState implements IBinder.DeathRecipient { public ObbState(String rawPath, String canonicalPath, int callingUid, IObbActionListener token, int nonce) { @@ -807,7 +803,7 @@ class MountService extends IMountService.Stub for (int i = 0; i < mVolumes.size(); i++) { final VolumeInfo vol = mVolumes.valueAt(i); if (vol.isVisibleToUser(userId) && vol.isMountedReadable()) { - final StorageVolume userVol = vol.buildStorageVolume(mContext, userId); + final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); final String envState = VolumeInfo.getEnvironmentForState(vol.getState()); @@ -1250,7 +1246,7 @@ class MountService extends IMountService.Stub // user-specific broadcasts. for (int userId : mStartedUsers) { if (vol.isVisibleToUser(userId)) { - final StorageVolume userVol = vol.buildStorageVolume(mContext, userId); + final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv, @@ -1370,6 +1366,8 @@ class MountService extends IMountService.Stub readSettingsLocked(); } + LocalServices.addService(MountServiceInternal.class, mMountServiceInternal); + /* * Create the connection to vold with a maximum queue of twice the * amount of containers we'd ever expect to have. This keeps an @@ -1787,27 +1785,28 @@ class MountService extends IMountService.Stub } } - @Override - public void remountUid(int uid) { - enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); + private void remountUidExternalStorage(int uid, int mode) { 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"; + String modeName = "none"; + switch (mode) { + case Zygote.MOUNT_EXTERNAL_DEFAULT: { + modeName = "default"; + } break; + + case Zygote.MOUNT_EXTERNAL_READ: { + modeName = "read"; + } break; + + case Zygote.MOUNT_EXTERNAL_WRITE: { + modeName = "write"; + } break; } try { - mConnector.execute("volume", "remount_uid", uid, mode); + mConnector.execute("volume", "remount_uid", uid, modeName); } catch (NativeDaemonConnectorException e) { - Slog.w(TAG, "Failed to remount UID " + uid + " as " + mode + ": " + e); + Slog.w(TAG, "Failed to remount UID " + uid + " as " + modeName + ": " + e); } } @@ -2598,15 +2597,20 @@ class MountService extends IMountService.Stub } @Override - public StorageVolume[] getVolumeList(int userId) { + public StorageVolume[] getVolumeList(int uid, String packageName) { final ArrayList<StorageVolume> res = new ArrayList<>(); boolean foundPrimary = false; + final int userId = UserHandle.getUserId(uid); + final boolean reportUnmounted = !mMountServiceInternal.hasExternalStorage( + uid, packageName); + synchronized (mLock) { for (int i = 0; i < mVolumes.size(); i++) { final VolumeInfo vol = mVolumes.valueAt(i); if (vol.isVisibleToUser(userId)) { - final StorageVolume userVol = vol.buildStorageVolume(mContext, userId); + final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, + reportUnmounted); if (vol.isPrimary()) { res.add(0, userVol); foundPrimary = true; @@ -3379,4 +3383,50 @@ class MountService extends IMountService.Stub mCryptConnector.monitor(); } } + + private final class MountServiceInternalImpl extends MountServiceInternal { + // Not guarded by a lock. + private final CopyOnWriteArrayList<ExternalStorageMountPolicy> mPolicies = + new CopyOnWriteArrayList<>(); + + @Override + public void addExternalStoragePolicy(ExternalStorageMountPolicy policy) { + // No locking - CopyOnWriteArrayList + mPolicies.add(policy); + } + + @Override + public void onExternalStoragePolicyChanged(int uid, String packageName) { + final int mountMode = getExternalStorageMountMode(uid, packageName); + remountUidExternalStorage(uid, mountMode); + } + + @Override + public int getExternalStorageMountMode(int uid, String packageName) { + // No locking - CopyOnWriteArrayList + int mountMode = Integer.MAX_VALUE; + for (ExternalStorageMountPolicy policy : mPolicies) { + final int policyMode = policy.getMountMode(uid, packageName); + if (policyMode == Zygote.MOUNT_EXTERNAL_NONE) { + return Zygote.MOUNT_EXTERNAL_NONE; + } + mountMode = Math.min(mountMode, policyMode); + } + if (mountMode == Integer.MAX_VALUE) { + return Zygote.MOUNT_EXTERNAL_NONE; + } + return mountMode; + } + + public boolean hasExternalStorage(int uid, String packageName) { + // No locking - CopyOnWriteArrayList + for (ExternalStorageMountPolicy policy : mPolicies) { + final boolean policyHasStorage = policy.hasExternalStorage(uid, packageName); + if (!policyHasStorage) { + return false; + } + } + return true; + } + } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 6e94647..5bfca10 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -18,7 +18,10 @@ 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.Manifest.permission.WRITE_MEDIA_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; @@ -62,6 +65,7 @@ import android.os.Trace; import android.os.TransactionTooLargeException; import android.os.WorkSource; import android.os.storage.IMountService; +import android.os.storage.MountServiceInternal; import android.os.storage.StorageManager; import android.service.voice.IVoiceInteractionSession; import android.util.ArrayMap; @@ -3219,7 +3223,10 @@ public final class ActivityManagerService extends ActivityManagerNative checkTime(startTime, "startProcess: getting gids from package manager"); final IPackageManager pm = AppGlobals.getPackageManager(); permGids = pm.getPackageGids(app.info.packageName, app.userId); - mountExternal = pm.getMountExternalMode(uid); + MountServiceInternal mountServiceInternal = LocalServices.getService( + MountServiceInternal.class); + mountExternal = mountServiceInternal.getExternalStorageMountMode(uid, + app.info.packageName); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index bf250ce..24f3f7f 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -62,6 +62,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_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageParser.isApkFile; import static android.os.Process.PACKAGE_INFO_GID; @@ -165,6 +166,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.IMountService; +import android.os.storage.MountServiceInternal; import android.os.storage.StorageEventListener; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; @@ -2726,23 +2728,6 @@ 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_MEDIA_STORAGE, uid) == PERMISSION_GRANTED) { - return Zygote.MOUNT_EXTERNAL_DEFAULT; - } 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) { @@ -3465,8 +3450,9 @@ public class PackageManagerService extends IPackageManager.Stub { final long token = Binder.clearCallingIdentity(); try { if (sUserManager.isInitialized(userId)) { - final StorageManager storage = mContext.getSystemService(StorageManager.class); - storage.remountUid(uid); + MountServiceInternal mountServiceInternal = LocalServices.getService( + MountServiceInternal.class); + mountServiceInternal.onExternalStoragePolicyChanged(uid, packageName); } } finally { Binder.restoreCallingIdentity(token); @@ -14466,6 +14452,33 @@ public class PackageManagerService extends IPackageManager.Stub { mInstallerService.systemReady(); mPackageDexOptimizer.systemReady(); + + MountServiceInternal mountServiceInternal = LocalServices.getService( + MountServiceInternal.class); + mountServiceInternal.addExternalStoragePolicy( + new MountServiceInternal.ExternalStorageMountPolicy() { + @Override + public int getMountMode(int uid, String packageName) { + if (Process.isIsolated(uid)) { + return Zygote.MOUNT_EXTERNAL_NONE; + } + if (checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED) { + return Zygote.MOUNT_EXTERNAL_DEFAULT; + } + if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) { + return Zygote.MOUNT_EXTERNAL_DEFAULT; + } + if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) { + return Zygote.MOUNT_EXTERNAL_READ; + } + return Zygote.MOUNT_EXTERNAL_WRITE; + } + + @Override + public boolean hasExternalStorage(int uid, String packageName) { + return true; + } + }); } @Override |