summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/AppOpsManager.aidl20
-rw-r--r--core/java/android/app/AppOpsManager.java166
-rw-r--r--core/java/android/app/ContextImpl.java4
-rw-r--r--core/java/android/content/ContentProvider.java105
-rw-r--r--core/java/android/content/ContentProviderClient.java24
-rw-r--r--core/java/android/content/ContentProviderNative.java67
-rw-r--r--core/java/android/content/ContentResolver.java29
-rw-r--r--core/java/android/content/IContentProvider.java27
-rw-r--r--core/java/android/provider/Settings.java18
-rw-r--r--core/java/com/android/internal/app/IAppOpsService.aidl6
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);
}