summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Blitzstein <sblitz@google.com>2014-12-03 16:18:02 -0800
committerSam Blitzstein <sblitz@google.com>2014-12-10 14:58:53 -0800
commit96d67800c827efb5c08adaa32e221aaae53d02a4 (patch)
tree9c0d53b6a90df6c1005309714445247a45f94e31
parentd96b2bcc2b675b6e8eae54af31b51325ec73ce0a (diff)
downloadandroid_packages_providers_CalendarProvider-96d67800c827efb5c08adaa32e221aaae53d02a4.tar.gz
android_packages_providers_CalendarProvider-96d67800c827efb5c08adaa32e221aaae53d02a4.tar.bz2
android_packages_providers_CalendarProvider-96d67800c827efb5c08adaa32e221aaae53d02a4.zip
Before the first call to clearCallingIdentity, cache the calling package.
Then it will be saved as a mutator when the dirty bit is set. This may be accessed by multiple threads, so the data is cached in ThreadLocal. Also track the calling Uid, and clear the cached package when the tracked Uid is restored. Bug: 18421411 Change-Id: I4597bd4169636c3988d72ddde51578a02af193ea
-rw-r--r--src/com/android/providers/calendar/CalendarProvider2.java9
-rw-r--r--src/com/android/providers/calendar/SQLiteContentProvider.java75
2 files changed, 72 insertions, 12 deletions
diff --git a/src/com/android/providers/calendar/CalendarProvider2.java b/src/com/android/providers/calendar/CalendarProvider2.java
index 9af4c77..5002177 100644
--- a/src/com/android/providers/calendar/CalendarProvider2.java
+++ b/src/com/android/providers/calendar/CalendarProvider2.java
@@ -834,11 +834,11 @@ public class CalendarProvider2 extends SQLiteContentProvider implements OnAccoun
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
- final long identity = Binder.clearCallingIdentity();
+ final long identity = clearCallingIdentityInternal();
try {
return queryInternal(uri, projection, selection, selectionArgs, sortOrder);
} finally {
- Binder.restoreCallingIdentity(identity);
+ restoreCallingIdentityInternal(identity);
}
}
@@ -5074,6 +5074,11 @@ public class CalendarProvider2 extends SQLiteContentProvider implements OnAccoun
}
private String getCallingPackageName() {
+ if (getCachedCallingPackage() != null) {
+ // If the calling package is null, use the best available as a fallback.
+ return getCachedCallingPackage();
+ }
+
final PackageManager pm = getContext().getPackageManager();
final int uid = Binder.getCallingUid();
final String[] packages = pm.getPackagesForUid(uid);
diff --git a/src/com/android/providers/calendar/SQLiteContentProvider.java b/src/com/android/providers/calendar/SQLiteContentProvider.java
index ad0e028..01afb23 100644
--- a/src/com/android/providers/calendar/SQLiteContentProvider.java
+++ b/src/com/android/providers/calendar/SQLiteContentProvider.java
@@ -27,6 +27,7 @@ import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteTransactionListener;
import android.net.Uri;
import android.os.Binder;
+import android.os.Process;
import android.provider.CalendarContract;
import java.util.ArrayList;
@@ -93,7 +94,7 @@ public abstract class SQLiteContentProvider extends ContentProvider
if (!applyingBatch) {
mDb = mOpenHelper.getWritableDatabase();
mDb.beginTransactionWithListener(this);
- final long identity = Binder.clearCallingIdentity();
+ final long identity = clearCallingIdentityInternal();
try {
result = insertInTransaction(uri, values, isCallerSyncAdapter);
if (result != null) {
@@ -101,7 +102,7 @@ public abstract class SQLiteContentProvider extends ContentProvider
}
mDb.setTransactionSuccessful();
} finally {
- Binder.restoreCallingIdentity(identity);
+ restoreCallingIdentityInternal(identity);
mDb.endTransaction();
}
@@ -121,7 +122,7 @@ public abstract class SQLiteContentProvider extends ContentProvider
boolean isCallerSyncAdapter = getIsCallerSyncAdapter(uri);
mDb = mOpenHelper.getWritableDatabase();
mDb.beginTransactionWithListener(this);
- final long identity = Binder.clearCallingIdentity();
+ final long identity = clearCallingIdentityInternal();
try {
for (int i = 0; i < numValues; i++) {
Uri result = insertInTransaction(uri, values[i], isCallerSyncAdapter);
@@ -132,7 +133,7 @@ public abstract class SQLiteContentProvider extends ContentProvider
}
mDb.setTransactionSuccessful();
} finally {
- Binder.restoreCallingIdentity(identity);
+ restoreCallingIdentityInternal(identity);
mDb.endTransaction();
}
@@ -148,7 +149,7 @@ public abstract class SQLiteContentProvider extends ContentProvider
if (!applyingBatch) {
mDb = mOpenHelper.getWritableDatabase();
mDb.beginTransactionWithListener(this);
- final long identity = Binder.clearCallingIdentity();
+ final long identity = clearCallingIdentityInternal();
try {
count = updateInTransaction(uri, values, selection, selectionArgs,
isCallerSyncAdapter);
@@ -157,7 +158,7 @@ public abstract class SQLiteContentProvider extends ContentProvider
}
mDb.setTransactionSuccessful();
} finally {
- Binder.restoreCallingIdentity(identity);
+ restoreCallingIdentityInternal(identity);
mDb.endTransaction();
}
@@ -181,7 +182,7 @@ public abstract class SQLiteContentProvider extends ContentProvider
if (!applyingBatch) {
mDb = mOpenHelper.getWritableDatabase();
mDb.beginTransactionWithListener(this);
- final long identity = Binder.clearCallingIdentity();
+ final long identity = clearCallingIdentityInternal();
try {
count = deleteInTransaction(uri, selection, selectionArgs, isCallerSyncAdapter);
if (count > 0) {
@@ -189,7 +190,7 @@ public abstract class SQLiteContentProvider extends ContentProvider
}
mDb.setTransactionSuccessful();
} finally {
- Binder.restoreCallingIdentity(identity);
+ restoreCallingIdentityInternal(identity);
mDb.endTransaction();
}
@@ -222,7 +223,7 @@ public abstract class SQLiteContentProvider extends ContentProvider
mDb = mOpenHelper.getWritableDatabase();
mDb.beginTransactionWithListener(this);
final boolean isCallerSyncAdapter = getIsCallerSyncAdapter(operations.get(0).getUri());
- final long identity = Binder.clearCallingIdentity();
+ final long identity = clearCallingIdentityInternal();
try {
mApplyingBatch.set(true);
final ContentProviderResult[] results = new ContentProviderResult[numOperations];
@@ -239,7 +240,7 @@ public abstract class SQLiteContentProvider extends ContentProvider
mApplyingBatch.set(false);
mDb.endTransaction();
onEndTransaction(!isCallerSyncAdapter);
- Binder.restoreCallingIdentity(identity);
+ restoreCallingIdentityInternal(identity);
}
}
@@ -274,4 +275,58 @@ public abstract class SQLiteContentProvider extends ContentProvider
* Some URI's are maintained locally so we should not request a sync for them
*/
protected abstract boolean shouldSyncFor(Uri uri);
+
+ /** The package to most recently query(), not including further internally recursive calls. */
+ private final ThreadLocal<String> mCallingPackage = new ThreadLocal<String>();
+
+ /**
+ * The calling Uid when a calling package is cached, so we know when the stack of any
+ * recursive calls to clearCallingIdentity and restoreCallingIdentity is complete.
+ */
+ private final ThreadLocal<Integer> mOriginalCallingUid = new ThreadLocal<Integer>();
+
+
+ protected String getCachedCallingPackage() {
+ return mCallingPackage.get();
+ }
+
+ /**
+ * Call {@link android.os.Binder#clearCallingIdentity()}, while caching the calling package
+ * name, so that it can be saved if this is part of an event mutation.
+ */
+ protected long clearCallingIdentityInternal() {
+ // Only set the calling package if the calling UID is not our own.
+ int uid = Process.myUid();
+ int callingUid = Binder.getCallingUid();
+ if (uid != callingUid) {
+ try {
+ mOriginalCallingUid.set(callingUid);
+ String callingPackage = getCallingPackage();
+ mCallingPackage.set(callingPackage);
+ } catch (SecurityException e) {
+ // If this exception is thrown, clearCallingIdentity has already been called, and
+ // calling package is already available.
+ }
+ }
+
+ return Binder.clearCallingIdentity();
+ }
+
+ /**
+ * Call {@link Binder#restoreCallingIdentity(long)}.
+ * </p>
+ * If this is the last restore on the stack of calls to
+ * {@link android.os.Binder#clearCallingIdentity()}, then the cached calling package will also
+ * be cleared.
+ * @param identity
+ */
+ protected void restoreCallingIdentityInternal(long identity) {
+ Binder.restoreCallingIdentity(identity);
+
+ int callingUid = Binder.getCallingUid();
+ if (mOriginalCallingUid.get() != null && mOriginalCallingUid.get() == callingUid) {
+ mCallingPackage.set(null);
+ mOriginalCallingUid.set(null);
+ }
+ }
}