diff options
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/app/AppOpsManager.aidl | 20 | ||||
-rw-r--r-- | core/java/android/app/AppOpsManager.java | 166 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 4 | ||||
-rw-r--r-- | core/java/android/content/ContentProvider.java | 105 | ||||
-rw-r--r-- | core/java/android/content/ContentProviderClient.java | 24 | ||||
-rw-r--r-- | core/java/android/content/ContentProviderNative.java | 67 | ||||
-rw-r--r-- | core/java/android/content/ContentResolver.java | 29 | ||||
-rw-r--r-- | core/java/android/content/IContentProvider.java | 27 | ||||
-rw-r--r-- | core/java/android/provider/Settings.java | 18 | ||||
-rw-r--r-- | core/java/com/android/internal/app/IAppOpsService.aidl | 6 |
10 files changed, 374 insertions, 92 deletions
diff --git a/core/java/android/app/AppOpsManager.aidl b/core/java/android/app/AppOpsManager.aidl new file mode 100644 index 0000000..4b97a15 --- /dev/null +++ b/core/java/android/app/AppOpsManager.aidl @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2013, 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 android.app; + +parcelable AppOpsManager.PackageOps; +parcelable AppOpsManager.OpEntry; diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 7210df4..4cea6a0 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -18,7 +18,12 @@ package android.app; import com.android.internal.app.IAppOpsService; +import java.util.ArrayList; +import java.util.List; + import android.content.Context; +import android.os.Parcel; +import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; @@ -31,24 +36,177 @@ public class AppOpsManager { public static final int MODE_IGNORED = 1; public static final int MODE_ERRORED = 2; - public static final int OP_LOCATION = 0; - public static final int OP_GPS = 1; - public static final int OP_VIBRATE = 2; + public static final int OP_COARSE_LOCATION = 0; + public static final int OP_FINE_LOCATION = 1; + public static final int OP_GPS = 2; + public static final int OP_VIBRATE = 3; + public static final int OP_READ_CONTACTS = 4; + public static final int OP_WRITE_CONTACTS = 5; + public static final int OP_READ_CALL_LOG = 6; + public static final int OP_WRITE_CALL_LOG = 7; public static String opToString(int op) { switch (op) { - case OP_LOCATION: return "LOCATION"; + case OP_COARSE_LOCATION: return "COARSE_LOCATION"; + case OP_FINE_LOCATION: return "FINE_LOCATION"; case OP_GPS: return "GPS"; case OP_VIBRATE: return "VIBRATE"; + case OP_READ_CONTACTS: return "READ_CONTACTS"; + case OP_WRITE_CONTACTS: return "WRITE_CONTACTS"; + case OP_READ_CALL_LOG: return "READ_CALL_LOG"; + case OP_WRITE_CALL_LOG: return "WRITE_CALL_LOG"; default: return "Unknown(" + op + ")"; } } + public static class PackageOps implements Parcelable { + private final String mPackageName; + private final int mUid; + private final List<OpEntry> mEntries; + + public PackageOps(String packageName, int uid, List<OpEntry> entries) { + mPackageName = packageName; + mUid = uid; + mEntries = entries; + } + + public String getPackageName() { + return mPackageName; + } + + public int getUid() { + return mUid; + } + + public List<OpEntry> getOps() { + return mEntries; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mPackageName); + dest.writeInt(mUid); + dest.writeInt(mEntries.size()); + for (int i=0; i<mEntries.size(); i++) { + mEntries.get(i).writeToParcel(dest, flags); + } + } + + PackageOps(Parcel source) { + mPackageName = source.readString(); + mUid = source.readInt(); + mEntries = new ArrayList<OpEntry>(); + final int N = source.readInt(); + for (int i=0; i<N; i++) { + mEntries.add(OpEntry.CREATOR.createFromParcel(source)); + } + } + + public static final Creator<PackageOps> CREATOR = new Creator<PackageOps>() { + @Override public PackageOps createFromParcel(Parcel source) { + return new PackageOps(source); + } + + @Override public PackageOps[] newArray(int size) { + return new PackageOps[size]; + } + }; + } + + public static class OpEntry implements Parcelable { + private final int mOp; + private final long mTime; + private final int mDuration; + + public OpEntry(int op, long time, int duration) { + mOp = op; + mTime = time; + mDuration = duration; + } + + public int getOp() { + return mOp; + } + + public long getTime() { + return mTime; + } + + public boolean isRunning() { + return mDuration == -1; + } + + public int getDuration() { + return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mOp); + dest.writeLong(mTime); + dest.writeInt(mDuration); + } + + OpEntry(Parcel source) { + mOp = source.readInt(); + mTime = source.readLong(); + mDuration = source.readInt(); + } + + public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() { + @Override public OpEntry createFromParcel(Parcel source) { + return new OpEntry(source); + } + + @Override public OpEntry[] newArray(int size) { + return new OpEntry[size]; + } + }; + } + public AppOpsManager(Context context, IAppOpsService service) { mContext = context; mService = service; } + public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { + try { + return mService.getPackagesForOps(ops); + } catch (RemoteException e) { + } + return null; + } + + public int checkOp(int op, int uid, String packageName) { + try { + int mode = mService.checkOperation(op, uid, packageName); + if (mode == MODE_ERRORED) { + throw new SecurityException("Operation not allowed"); + } + return mode; + } catch (RemoteException e) { + } + return MODE_IGNORED; + } + + public int checkOpNoThrow(int op, int uid, String packageName) { + try { + return mService.checkOperation(op, uid, packageName); + } catch (RemoteException e) { + } + return MODE_IGNORED; + } + public int noteOp(int op, int uid, String packageName) { try { int mode = mService.noteOperation(op, uid, packageName); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 99ac0d6..1d394e8 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -623,7 +623,9 @@ class ContextImpl extends Context { if (mPackageInfo != null) { return mPackageInfo.getPackageName(); } - throw new RuntimeException("Not supported in system context"); + // No mPackageInfo means this is a Context for the system itself, + // and this here is its name. + return "android"; } @Override diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index c1411b0..a6f7abc 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -18,6 +18,7 @@ package android.content; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import android.app.AppOpsManager; import android.content.pm.PackageManager; import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; @@ -172,6 +173,10 @@ public abstract class ContentProvider implements ComponentCallbacks2 { * @hide */ class Transport extends ContentProviderNative { + AppOpsManager mAppOpsManager = null; + int mReadOp = -1; + int mWriteOp = -1; + ContentProvider getContentProvider() { return ContentProvider.this; } @@ -182,10 +187,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 { } @Override - public Cursor query(Uri uri, String[] projection, + public Cursor query(String callingPkg, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, ICancellationSignal cancellationSignal) { - enforceReadPermission(uri); + // XXX need content provider to help return correct result. + enforceReadPermission(callingPkg, uri); return ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder, CancellationSignal.fromTransport(cancellationSignal)); } @@ -196,63 +202,75 @@ public abstract class ContentProvider implements ComponentCallbacks2 { } @Override - public Uri insert(Uri uri, ContentValues initialValues) { - enforceWritePermission(uri); + public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) { + // XXX need content provider to help return correct result. + enforceWritePermission(callingPkg, uri); return ContentProvider.this.insert(uri, initialValues); } @Override - public int bulkInsert(Uri uri, ContentValues[] initialValues) { - enforceWritePermission(uri); + public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) { + if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { + return 0; + } return ContentProvider.this.bulkInsert(uri, initialValues); } @Override - public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) + public ContentProviderResult[] applyBatch(String callingPkg, + ArrayList<ContentProviderOperation> operations) throws OperationApplicationException { for (ContentProviderOperation operation : operations) { if (operation.isReadOperation()) { - enforceReadPermission(operation.getUri()); + if (enforceReadPermission(callingPkg, operation.getUri()) + != AppOpsManager.MODE_ALLOWED) { + throw new OperationApplicationException("App op not allowed", 0); + } } if (operation.isWriteOperation()) { - enforceWritePermission(operation.getUri()); + if (enforceWritePermission(callingPkg, operation.getUri()) + != AppOpsManager.MODE_ALLOWED) { + throw new OperationApplicationException("App op not allowed", 0); + } } } return ContentProvider.this.applyBatch(operations); } @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - enforceWritePermission(uri); + public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) { + if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { + return 0; + } return ContentProvider.this.delete(uri, selection, selectionArgs); } @Override - public int update(Uri uri, ContentValues values, String selection, + public int update(String callingPkg, Uri uri, ContentValues values, String selection, String[] selectionArgs) { - enforceWritePermission(uri); + if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { + return 0; + } return ContentProvider.this.update(uri, values, selection, selectionArgs); } @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) + public ParcelFileDescriptor openFile(String callingPkg, Uri uri, String mode) throws FileNotFoundException { - if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri); - else enforceReadPermission(uri); + enforceFilePermission(callingPkg, uri, mode); return ContentProvider.this.openFile(uri, mode); } @Override - public AssetFileDescriptor openAssetFile(Uri uri, String mode) + public AssetFileDescriptor openAssetFile(String callingPkg, Uri uri, String mode) throws FileNotFoundException { - if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri); - else enforceReadPermission(uri); + enforceFilePermission(callingPkg, uri, mode); return ContentProvider.this.openAssetFile(uri, mode); } @Override - public Bundle call(String method, String arg, Bundle extras) { + public Bundle call(String callingPkg, String method, String arg, Bundle extras) { return ContentProvider.this.call(method, arg, extras); } @@ -262,9 +280,9 @@ public abstract class ContentProvider implements ComponentCallbacks2 { } @Override - public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeType, Bundle opts) - throws FileNotFoundException { - enforceReadPermission(uri); + public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType, + Bundle opts) throws FileNotFoundException { + enforceFilePermission(callingPkg, uri, "r"); return ContentProvider.this.openTypedAssetFile(uri, mimeType, opts); } @@ -273,7 +291,28 @@ public abstract class ContentProvider implements ComponentCallbacks2 { return CancellationSignal.createTransport(); } - private void enforceReadPermission(Uri uri) throws SecurityException { + private void enforceFilePermission(String callingPkg, Uri uri, String mode) + throws FileNotFoundException, SecurityException { + if (mode != null && mode.startsWith("rw")) { + if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { + throw new FileNotFoundException("App op not allowed"); + } + } else { + if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { + throw new FileNotFoundException("App op not allowed"); + } + } + } + + private int enforceReadPermission(String callingPkg, Uri uri) throws SecurityException { + enforceReadPermissionInner(uri); + if (mAppOpsManager != null) { + return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg); + } + return AppOpsManager.MODE_ALLOWED; + } + + private void enforceReadPermissionInner(Uri uri) throws SecurityException { final Context context = getContext(); final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); @@ -334,7 +373,15 @@ public abstract class ContentProvider implements ComponentCallbacks2 { + ", uid=" + uid + failReason); } - private void enforceWritePermission(Uri uri) throws SecurityException { + private int enforceWritePermission(String callingPkg, Uri uri) throws SecurityException { + enforceWritePermissionInner(uri); + if (mAppOpsManager != null) { + return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg); + } + return AppOpsManager.MODE_ALLOWED; + } + + private void enforceWritePermissionInner(Uri uri) throws SecurityException { final Context context = getContext(); final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); @@ -471,6 +518,14 @@ public abstract class ContentProvider implements ComponentCallbacks2 { return mPathPermissions; } + /** @hide */ + public final void setAppOps(int readOp, int writeOp) { + mTransport.mAppOpsManager = (AppOpsManager)mContext.getSystemService( + Context.APP_OPS_SERVICE); + mTransport.mReadOp = readOp; + mTransport.mWriteOp = writeOp; + } + /** * Implement this to initialize your content provider on startup. * This method is called for all registered content providers on the diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java index 204f963..8dffac7 100644 --- a/core/java/android/content/ContentProviderClient.java +++ b/core/java/android/content/ContentProviderClient.java @@ -45,6 +45,7 @@ import java.util.ArrayList; public class ContentProviderClient { private final IContentProvider mContentProvider; private final ContentResolver mContentResolver; + private final String mPackageName; private final boolean mStable; private boolean mReleased; @@ -55,6 +56,7 @@ public class ContentProviderClient { IContentProvider contentProvider, boolean stable) { mContentProvider = contentProvider; mContentResolver = contentResolver; + mPackageName = contentResolver.mPackageName; mStable = stable; } @@ -81,8 +83,8 @@ public class ContentProviderClient { cancellationSignal.setRemote(remoteCancellationSignal); } try { - return mContentProvider.query(url, projection, selection, selectionArgs, sortOrder, - remoteCancellationSignal); + return mContentProvider.query(mPackageName, url, projection, selection, selectionArgs, + sortOrder, remoteCancellationSignal); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -119,7 +121,7 @@ public class ContentProviderClient { public Uri insert(Uri url, ContentValues initialValues) throws RemoteException { try { - return mContentProvider.insert(url, initialValues); + return mContentProvider.insert(mPackageName, url, initialValues); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -131,7 +133,7 @@ public class ContentProviderClient { /** See {@link ContentProvider#bulkInsert ContentProvider.bulkInsert} */ public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException { try { - return mContentProvider.bulkInsert(url, initialValues); + return mContentProvider.bulkInsert(mPackageName, url, initialValues); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -144,7 +146,7 @@ public class ContentProviderClient { public int delete(Uri url, String selection, String[] selectionArgs) throws RemoteException { try { - return mContentProvider.delete(url, selection, selectionArgs); + return mContentProvider.delete(mPackageName, url, selection, selectionArgs); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -157,7 +159,7 @@ public class ContentProviderClient { public int update(Uri url, ContentValues values, String selection, String[] selectionArgs) throws RemoteException { try { - return mContentProvider.update(url, values, selection, selectionArgs); + return mContentProvider.update(mPackageName, url, values, selection, selectionArgs); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -176,7 +178,7 @@ public class ContentProviderClient { public ParcelFileDescriptor openFile(Uri url, String mode) throws RemoteException, FileNotFoundException { try { - return mContentProvider.openFile(url, mode); + return mContentProvider.openFile(mPackageName, url, mode); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -195,7 +197,7 @@ public class ContentProviderClient { public AssetFileDescriptor openAssetFile(Uri url, String mode) throws RemoteException, FileNotFoundException { try { - return mContentProvider.openAssetFile(url, mode); + return mContentProvider.openAssetFile(mPackageName, url, mode); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -209,7 +211,7 @@ public class ContentProviderClient { String mimeType, Bundle opts) throws RemoteException, FileNotFoundException { try { - return mContentProvider.openTypedAssetFile(uri, mimeType, opts); + return mContentProvider.openTypedAssetFile(mPackageName, uri, mimeType, opts); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -222,7 +224,7 @@ public class ContentProviderClient { public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) throws RemoteException, OperationApplicationException { try { - return mContentProvider.applyBatch(operations); + return mContentProvider.applyBatch(mPackageName, operations); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); @@ -235,7 +237,7 @@ public class ContentProviderClient { public Bundle call(String method, String arg, Bundle extras) throws RemoteException { try { - return mContentProvider.call(method, arg, extras); + return mContentProvider.call(mPackageName, method, arg, extras); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java index 384ba57..6f822c1 100644 --- a/core/java/android/content/ContentProviderNative.java +++ b/core/java/android/content/ContentProviderNative.java @@ -81,6 +81,7 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); + String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); // String[] projection @@ -110,8 +111,8 @@ abstract public class ContentProviderNative extends Binder implements IContentPr ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface( data.readStrongBinder()); - Cursor cursor = query(url, projection, selection, selectionArgs, sortOrder, - cancellationSignal); + Cursor cursor = query(callingPkg, url, projection, selection, selectionArgs, + sortOrder, cancellationSignal); if (cursor != null) { try { CursorToBulkCursorAdaptor adaptor = new CursorToBulkCursorAdaptor( @@ -150,10 +151,11 @@ abstract public class ContentProviderNative extends Binder implements IContentPr case INSERT_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); + String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); ContentValues values = ContentValues.CREATOR.createFromParcel(data); - Uri out = insert(url, values); + Uri out = insert(callingPkg, url, values); reply.writeNoException(); Uri.writeToParcel(reply, out); return true; @@ -162,10 +164,11 @@ abstract public class ContentProviderNative extends Binder implements IContentPr case BULK_INSERT_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); + String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); ContentValues[] values = data.createTypedArray(ContentValues.CREATOR); - int count = bulkInsert(url, values); + int count = bulkInsert(callingPkg, url, values); reply.writeNoException(); reply.writeInt(count); return true; @@ -174,13 +177,14 @@ abstract public class ContentProviderNative extends Binder implements IContentPr case APPLY_BATCH_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); + String callingPkg = data.readString(); final int numOperations = data.readInt(); final ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(numOperations); for (int i = 0; i < numOperations; i++) { operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data)); } - final ContentProviderResult[] results = applyBatch(operations); + final ContentProviderResult[] results = applyBatch(callingPkg, operations); reply.writeNoException(); reply.writeTypedArray(results, 0); return true; @@ -189,11 +193,12 @@ abstract public class ContentProviderNative extends Binder implements IContentPr case DELETE_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); + String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); String selection = data.readString(); String[] selectionArgs = data.readStringArray(); - int count = delete(url, selection, selectionArgs); + int count = delete(callingPkg, url, selection, selectionArgs); reply.writeNoException(); reply.writeInt(count); @@ -203,12 +208,13 @@ abstract public class ContentProviderNative extends Binder implements IContentPr case UPDATE_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); + String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); ContentValues values = ContentValues.CREATOR.createFromParcel(data); String selection = data.readString(); String[] selectionArgs = data.readStringArray(); - int count = update(url, values, selection, selectionArgs); + int count = update(callingPkg, url, values, selection, selectionArgs); reply.writeNoException(); reply.writeInt(count); @@ -218,11 +224,12 @@ abstract public class ContentProviderNative extends Binder implements IContentPr case OPEN_FILE_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); + String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); String mode = data.readString(); ParcelFileDescriptor fd; - fd = openFile(url, mode); + fd = openFile(callingPkg, url, mode); reply.writeNoException(); if (fd != null) { reply.writeInt(1); @@ -237,11 +244,12 @@ abstract public class ContentProviderNative extends Binder implements IContentPr case OPEN_ASSET_FILE_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); + String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); String mode = data.readString(); AssetFileDescriptor fd; - fd = openAssetFile(url, mode); + fd = openAssetFile(callingPkg, url, mode); reply.writeNoException(); if (fd != null) { reply.writeInt(1); @@ -257,11 +265,12 @@ abstract public class ContentProviderNative extends Binder implements IContentPr { data.enforceInterface(IContentProvider.descriptor); + String callingPkg = data.readString(); String method = data.readString(); String stringArg = data.readString(); Bundle args = data.readBundle(); - Bundle responseBundle = call(method, stringArg, args); + Bundle responseBundle = call(callingPkg, method, stringArg, args); reply.writeNoException(); reply.writeBundle(responseBundle); @@ -283,12 +292,13 @@ abstract public class ContentProviderNative extends Binder implements IContentPr case OPEN_TYPED_ASSET_FILE_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); + String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); String mimeType = data.readString(); Bundle opts = data.readBundle(); AssetFileDescriptor fd; - fd = openTypedAssetFile(url, mimeType, opts); + fd = openTypedAssetFile(callingPkg, url, mimeType, opts); reply.writeNoException(); if (fd != null) { reply.writeInt(1); @@ -337,7 +347,7 @@ final class ContentProviderProxy implements IContentProvider return mRemote; } - public Cursor query(Uri url, String[] projection, String selection, + public Cursor query(String callingPkg, Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder, ICancellationSignal cancellationSignal) throws RemoteException { BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor(); @@ -346,6 +356,7 @@ final class ContentProviderProxy implements IContentProvider try { data.writeInterfaceToken(IContentProvider.descriptor); + data.writeString(callingPkg); url.writeToParcel(data, 0); int length = 0; if (projection != null) { @@ -413,13 +424,14 @@ final class ContentProviderProxy implements IContentProvider } } - public Uri insert(Uri url, ContentValues values) throws RemoteException + public Uri insert(String callingPkg, Uri url, ContentValues values) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); + data.writeString(callingPkg); url.writeToParcel(data, 0); values.writeToParcel(data, 0); @@ -434,12 +446,13 @@ final class ContentProviderProxy implements IContentProvider } } - public int bulkInsert(Uri url, ContentValues[] values) throws RemoteException { + public int bulkInsert(String callingPkg, Uri url, ContentValues[] values) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); + data.writeString(callingPkg); url.writeToParcel(data, 0); data.writeTypedArray(values, 0); @@ -454,12 +467,14 @@ final class ContentProviderProxy implements IContentProvider } } - public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) - throws RemoteException, OperationApplicationException { + public ContentProviderResult[] applyBatch(String callingPkg, + ArrayList<ContentProviderOperation> operations) + throws RemoteException, OperationApplicationException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); + data.writeString(callingPkg); data.writeInt(operations.size()); for (ContentProviderOperation operation : operations) { operation.writeToParcel(data, 0); @@ -476,13 +491,14 @@ final class ContentProviderProxy implements IContentProvider } } - public int delete(Uri url, String selection, String[] selectionArgs) + public int delete(String callingPkg, Uri url, String selection, String[] selectionArgs) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); + data.writeString(callingPkg); url.writeToParcel(data, 0); data.writeString(selection); data.writeStringArray(selectionArgs); @@ -498,13 +514,14 @@ final class ContentProviderProxy implements IContentProvider } } - public int update(Uri url, ContentValues values, String selection, + public int update(String callingPkg, Uri url, ContentValues values, String selection, String[] selectionArgs) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); + data.writeString(callingPkg); url.writeToParcel(data, 0); values.writeToParcel(data, 0); data.writeString(selection); @@ -521,13 +538,14 @@ final class ContentProviderProxy implements IContentProvider } } - public ParcelFileDescriptor openFile(Uri url, String mode) + public ParcelFileDescriptor openFile(String callingPkg, Uri url, String mode) throws RemoteException, FileNotFoundException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); + data.writeString(callingPkg); url.writeToParcel(data, 0); data.writeString(mode); @@ -543,13 +561,14 @@ final class ContentProviderProxy implements IContentProvider } } - public AssetFileDescriptor openAssetFile(Uri url, String mode) + public AssetFileDescriptor openAssetFile(String callingPkg, Uri url, String mode) throws RemoteException, FileNotFoundException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); + data.writeString(callingPkg); url.writeToParcel(data, 0); data.writeString(mode); @@ -566,13 +585,14 @@ final class ContentProviderProxy implements IContentProvider } } - public Bundle call(String method, String request, Bundle args) + public Bundle call(String callingPkg, String method, String request, Bundle args) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); + data.writeString(callingPkg); data.writeString(method); data.writeString(request); data.writeBundle(args); @@ -609,13 +629,14 @@ final class ContentProviderProxy implements IContentProvider } } - public AssetFileDescriptor openTypedAssetFile(Uri url, String mimeType, Bundle opts) - throws RemoteException, FileNotFoundException { + public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri url, String mimeType, + Bundle opts) throws RemoteException, FileNotFoundException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); + data.writeString(callingPkg); url.writeToParcel(data, 0); data.writeString(mimeType); data.writeBundle(opts); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 86bf8c2..51c9aa5 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -207,6 +207,7 @@ public abstract class ContentResolver { public ContentResolver(Context context) { mContext = context; + mPackageName = context.getPackageName(); } /** @hide */ @@ -392,7 +393,7 @@ public abstract class ContentResolver { cancellationSignal.setRemote(remoteCancellationSignal); } try { - qCursor = unstableProvider.query(uri, projection, + qCursor = unstableProvider.query(mPackageName, uri, projection, selection, selectionArgs, sortOrder, remoteCancellationSignal); } catch (DeadObjectException e) { // The remote process has died... but we only hold an unstable @@ -403,7 +404,7 @@ public abstract class ContentResolver { if (stableProvider == null) { return null; } - qCursor = stableProvider.query(uri, projection, + qCursor = stableProvider.query(mPackageName, uri, projection, selection, selectionArgs, sortOrder, remoteCancellationSignal); } if (qCursor == null) { @@ -651,7 +652,7 @@ public abstract class ContentResolver { try { try { - fd = unstableProvider.openAssetFile(uri, mode); + fd = unstableProvider.openAssetFile(mPackageName, uri, mode); if (fd == null) { // The provider will be released by the finally{} clause return null; @@ -665,7 +666,7 @@ public abstract class ContentResolver { if (stableProvider == null) { throw new FileNotFoundException("No content provider: " + uri); } - fd = stableProvider.openAssetFile(uri, mode); + fd = stableProvider.openAssetFile(mPackageName, uri, mode); if (fd == null) { // The provider will be released by the finally{} clause return null; @@ -743,7 +744,7 @@ public abstract class ContentResolver { try { try { - fd = unstableProvider.openTypedAssetFile(uri, mimeType, opts); + fd = unstableProvider.openTypedAssetFile(mPackageName, uri, mimeType, opts); if (fd == null) { // The provider will be released by the finally{} clause return null; @@ -757,7 +758,7 @@ public abstract class ContentResolver { if (stableProvider == null) { throw new FileNotFoundException("No content provider: " + uri); } - fd = stableProvider.openTypedAssetFile(uri, mimeType, opts); + fd = stableProvider.openTypedAssetFile(mPackageName, uri, mimeType, opts); if (fd == null) { // The provider will be released by the finally{} clause return null; @@ -892,7 +893,7 @@ public abstract class ContentResolver { } try { long startTime = SystemClock.uptimeMillis(); - Uri createdRow = provider.insert(url, values); + Uri createdRow = provider.insert(mPackageName, url, values); long durationMillis = SystemClock.uptimeMillis() - startTime; maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */); return createdRow; @@ -953,7 +954,7 @@ public abstract class ContentResolver { } try { long startTime = SystemClock.uptimeMillis(); - int rowsCreated = provider.bulkInsert(url, values); + int rowsCreated = provider.bulkInsert(mPackageName, url, values); long durationMillis = SystemClock.uptimeMillis() - startTime; maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */); return rowsCreated; @@ -984,7 +985,7 @@ public abstract class ContentResolver { } try { long startTime = SystemClock.uptimeMillis(); - int rowsDeleted = provider.delete(url, where, selectionArgs); + int rowsDeleted = provider.delete(mPackageName, url, where, selectionArgs); long durationMillis = SystemClock.uptimeMillis() - startTime; maybeLogUpdateToEventLog(durationMillis, url, "delete", where); return rowsDeleted; @@ -1018,7 +1019,7 @@ public abstract class ContentResolver { } try { long startTime = SystemClock.uptimeMillis(); - int rowsUpdated = provider.update(uri, values, where, selectionArgs); + int rowsUpdated = provider.update(mPackageName, uri, values, where, selectionArgs); long durationMillis = SystemClock.uptimeMillis() - startTime; maybeLogUpdateToEventLog(durationMillis, uri, "update", where); return rowsUpdated; @@ -1057,7 +1058,7 @@ public abstract class ContentResolver { throw new IllegalArgumentException("Unknown URI " + uri); } try { - return provider.call(method, arg, extras); + return provider.call(mPackageName, method, arg, extras); } catch (RemoteException e) { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. @@ -1955,7 +1956,13 @@ public abstract class ContentResolver { return sContentService; } + /** @hide */ + public String getPackageName() { + return mPackageName; + } + private static IContentService sContentService; private final Context mContext; + final String mPackageName; private static final String TAG = "ContentResolver"; } diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java index eeba1e0..62b79f0 100644 --- a/core/java/android/content/IContentProvider.java +++ b/core/java/android/content/IContentProvider.java @@ -34,30 +34,33 @@ import java.util.ArrayList; * @hide */ public interface IContentProvider extends IInterface { - public Cursor query(Uri url, String[] projection, String selection, + public Cursor query(String callingPkg, Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder, ICancellationSignal cancellationSignal) throws RemoteException; public String getType(Uri url) throws RemoteException; - public Uri insert(Uri url, ContentValues initialValues) + public Uri insert(String callingPkg, Uri url, ContentValues initialValues) throws RemoteException; - public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException; - public int delete(Uri url, String selection, String[] selectionArgs) + public int bulkInsert(String callingPkg, Uri url, ContentValues[] initialValues) throws RemoteException; - public int update(Uri url, ContentValues values, String selection, + public int delete(String callingPkg, Uri url, String selection, String[] selectionArgs) + throws RemoteException; + public int update(String callingPkg, Uri url, ContentValues values, String selection, String[] selectionArgs) throws RemoteException; - public ParcelFileDescriptor openFile(Uri url, String mode) + public ParcelFileDescriptor openFile(String callingPkg, Uri url, String mode) throws RemoteException, FileNotFoundException; - public AssetFileDescriptor openAssetFile(Uri url, String mode) + public AssetFileDescriptor openAssetFile(String callingPkg, Uri url, String mode) throws RemoteException, FileNotFoundException; - public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) - throws RemoteException, OperationApplicationException; - public Bundle call(String method, String arg, Bundle extras) throws RemoteException; + public ContentProviderResult[] applyBatch(String callingPkg, + ArrayList<ContentProviderOperation> operations) + throws RemoteException, OperationApplicationException; + public Bundle call(String callingPkg, String method, String arg, Bundle extras) + throws RemoteException; public ICancellationSignal createCancellationSignal() throws RemoteException; // Data interchange. public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException; - public AssetFileDescriptor openTypedAssetFile(Uri url, String mimeType, Bundle opts) - throws RemoteException, FileNotFoundException; + public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri url, String mimeType, + Bundle opts) throws RemoteException, FileNotFoundException; /* IPC constants */ static final String descriptor = "android.content.IContentProvider"; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 441214c..3d850cf 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -456,6 +456,18 @@ public final class Settings { "android.settings.APPLICATION_DETAILS_SETTINGS"; /** + * @hide + * Activity Action: Show the "app ops" settings screen. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_APP_OPS_SETTINGS = + "android.settings.APP_OPS_SETTINGS"; + + /** * Activity Action: Show settings for system update functionality. * <p> * In some cases, a matching Activity may not exist, so ensure you @@ -774,7 +786,7 @@ public final class Settings { arg.putString(Settings.NameValueTable.VALUE, value); arg.putInt(CALL_METHOD_USER_KEY, userHandle); IContentProvider cp = lazyGetProvider(cr); - cp.call(mCallSetCommand, name, arg); + cp.call(cr.getPackageName(), mCallSetCommand, name, arg); } catch (RemoteException e) { Log.w(TAG, "Can't set key " + name + " in " + mUri, e); return false; @@ -821,7 +833,7 @@ public final class Settings { args = new Bundle(); args.putInt(CALL_METHOD_USER_KEY, userHandle); } - Bundle b = cp.call(mCallGetCommand, name, args); + Bundle b = cp.call(cr.getPackageName(), mCallGetCommand, name, args); if (b != null) { String value = b.getPairValue(); // Don't update our cache for reads of other users' data @@ -846,7 +858,7 @@ public final class Settings { Cursor c = null; try { - c = cp.query(mUri, SELECT_VALUE, NAME_EQ_PLACEHOLDER, + c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE, NAME_EQ_PLACEHOLDER, new String[]{name}, null, null); if (c == null) { Log.w(TAG, "Can't get key " + name + " from " + mUri); diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index c934587..827dba6 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -16,10 +16,12 @@ package com.android.internal.app; +import android.app.AppOpsManager; + interface IAppOpsService { + List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops); + int checkOperation(int code, int uid, String packageName); int noteOperation(int code, int uid, String packageName); int startOperation(int code, int uid, String packageName); void finishOperation(int code, int uid, String packageName); - int noteTimedOperation(int code, int uid, String packageName, int duration); - void earlyFinishOperation(int code, int uid, String packageName); } |