diff options
author | Dianne Hackborn <hackbod@google.com> | 2010-08-25 22:00:28 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-08-25 22:00:28 -0700 |
commit | 3003a017d312a55e3804d6cf4a80044b1f1d7993 (patch) | |
tree | bfd0910b8bde42c17967399981b5a347069eae18 | |
parent | 14e00621c81da6a0391da47afce77945b27c7231 (diff) | |
parent | 7e269644fcc319835f1e7f762f3cbd8087e3e22f (diff) | |
download | frameworks_base-3003a017d312a55e3804d6cf4a80044b1f1d7993.zip frameworks_base-3003a017d312a55e3804d6cf4a80044b1f1d7993.tar.gz frameworks_base-3003a017d312a55e3804d6cf4a80044b1f1d7993.tar.bz2 |
Merge "Don't retain global ref to last inflated context." into gingerbread
9 files changed, 376 insertions, 145 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 9a55a6f..1d1b4dc 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1248,8 +1248,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case IS_USER_A_MONKEY_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - reply.writeInt(isUserAMonkey() ? 1 : 0); + boolean areThey = isUserAMonkey(); reply.writeNoException(); + reply.writeInt(areThey ? 1 : 0); return true; } @@ -1263,8 +1264,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case IS_IMMERSIVE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); - reply.writeInt(isImmersive(token) ? 1 : 0); + boolean isit = isImmersive(token); reply.writeNoException(); + reply.writeInt(isit ? 1 : 0); return true; } @@ -1279,8 +1281,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - reply.writeInt(isTopActivityImmersive() ? 1 : 0); + boolean isit = isTopActivityImmersive(); reply.writeNoException(); + reply.writeInt(isit ? 1 : 0); return true; } @@ -1295,6 +1298,40 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case NEW_URI_PERMISSION_OWNER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + String name = data.readString(); + IBinder perm = newUriPermissionOwner(name); + reply.writeNoException(); + reply.writeStrongBinder(perm); + return true; + } + + case GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder owner = data.readStrongBinder(); + int fromUid = data.readInt(); + String targetPkg = data.readString(); + Uri uri = Uri.CREATOR.createFromParcel(data); + int mode = data.readInt(); + grantUriPermissionFromOwner(owner, fromUid, targetPkg, uri, mode); + reply.writeNoException(); + return true; + } + + case REVOKE_URI_PERMISSION_FROM_OWNER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder owner = data.readStrongBinder(); + Uri uri = null; + if (data.readInt() != 0) { + Uri.CREATOR.createFromParcel(data); + } + int mode = data.readInt(); + revokeUriPermissionFromOwner(owner, uri, mode); + reply.writeNoException(); + return true; + } + } return super.onTransact(code, data, reply, flags); @@ -2841,8 +2878,8 @@ class ActivityManagerProxy implements IActivityManager data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); mRemote.transact(IS_IMMERSIVE_TRANSACTION, data, reply, 0); - boolean res = reply.readInt() == 1; reply.readException(); + boolean res = reply.readInt() == 1; data.recycle(); reply.recycle(); return res; @@ -2854,8 +2891,8 @@ class ActivityManagerProxy implements IActivityManager Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); mRemote.transact(IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION, data, reply, 0); - boolean res = reply.readInt() == 1; reply.readException(); + boolean res = reply.readInt() == 1; data.recycle(); reply.recycle(); return res; @@ -2875,6 +2912,55 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } + + public IBinder newUriPermissionOwner(String name) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(name); + mRemote.transact(NEW_URI_PERMISSION_OWNER_TRANSACTION, data, reply, 0); + reply.readException(); + IBinder res = reply.readStrongBinder(); + data.recycle(); + reply.recycle(); + return res; + } + + public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg, + Uri uri, int mode) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(owner); + data.writeInt(fromUid); + data.writeString(targetPkg); + uri.writeToParcel(data, 0); + data.writeInt(mode); + mRemote.transact(GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + public void revokeUriPermissionFromOwner(IBinder owner, Uri uri, + int mode) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(owner); + if (uri != null) { + data.writeInt(1); + uri.writeToParcel(data, 0); + } else { + data.writeInt(0); + } + data.writeInt(mode); + mRemote.transact(REVOKE_URI_PERMISSION_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } private IBinder mRemote; } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 416f289..664cf18 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -318,6 +318,12 @@ public interface IActivityManager extends IInterface { public void crashApplication(int uid, int initialPid, String packageName, String message) throws RemoteException; + public IBinder newUriPermissionOwner(String name) throws RemoteException; + public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg, + Uri uri, int mode) throws RemoteException; + public void revokeUriPermissionFromOwner(IBinder owner, Uri uri, + int mode) throws RemoteException; + /* * Private non-Binder interfaces */ @@ -524,4 +530,7 @@ public interface IActivityManager extends IInterface { int SET_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+111; int IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+112; int CRASH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+113; + int NEW_URI_PERMISSION_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+114; + int GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+115; + int REVOKE_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+116; } diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index e5985c1..3228127 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -434,6 +434,10 @@ public abstract class LayoutInflater { throw ex; } + // Told retain static reference on context. + mConstructorArgs[0] = null; + mConstructorArgs[1] = null; + return result; } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index c316074..d535343 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -4294,12 +4294,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen + " when granting permission to uri " + uri); } if (targetPkg == null) { - Slog.w(TAG, "grantUriPermission: null target"); - return; + throw new IllegalArgumentException("null target"); } if (uri == null) { - Slog.w(TAG, "grantUriPermission: null uri"); - return; + throw new IllegalArgumentException("null uri"); } grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags, @@ -4451,6 +4449,56 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } + @Override + public IBinder newUriPermissionOwner(String name) { + synchronized(this) { + UriPermissionOwner owner = new UriPermissionOwner(this, name); + return owner.getExternalTokenLocked(); + } + } + + @Override + public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg, + Uri uri, int modeFlags) { + synchronized(this) { + UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token); + if (owner == null) { + throw new IllegalArgumentException("Unknown owner: " + token); + } + if (fromUid != Binder.getCallingUid()) { + if (Binder.getCallingUid() != Process.myUid()) { + // Only system code can grant URI permissions on behalf + // of other users. + throw new SecurityException("nice try"); + } + } + if (targetPkg == null) { + throw new IllegalArgumentException("null target"); + } + if (uri == null) { + throw new IllegalArgumentException("null uri"); + } + + grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner); + } + } + + @Override + public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) { + synchronized(this) { + UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token); + if (owner == null) { + throw new IllegalArgumentException("Unknown owner: " + token); + } + + if (uri == null) { + owner.removeUriPermissionsLocked(mode); + } else { + owner.removeUriPermissionLocked(uri, mode); + } + } + } + public void showWaitingForDebugger(IApplicationThread who, boolean waiting) { synchronized (this) { ProcessRecord app = @@ -8260,7 +8308,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen si.deliveryCount++; if (si.targetPermissionUid >= 0) { grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid, - r.packageName, si.intent, si); + r.packageName, si.intent, si.getUriPermissionsLocked()); } if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r); bumpServiceExecutingLocked(r); diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 80a41b7..62be918 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -44,7 +44,7 @@ import java.util.HashSet; /** * An entry in the history stack, representing an activity. */ -class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwner { +class ActivityRecord extends IApplicationToken.Stub { final ActivityManagerService service; // owner final ActivityStack stack; // owner final ActivityInfo info; // all about me @@ -78,8 +78,7 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act ArrayList newIntents; // any pending new intents for single-top mode HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold - HashSet<UriPermission> readUriPermissions; // special access to reading uris. - HashSet<UriPermission> writeUriPermissions; // special access to writing uris. + UriPermissionOwner uriPermissions; // current special URI access perms. ProcessRecord app; // if non-null, hosting application Bitmap thumbnail; // icon representation of paused screen CharSequence description; // textual description of paused screen @@ -141,11 +140,15 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne if (pendingResults != null) { pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults); } - if (readUriPermissions != null) { - pw.print(prefix); pw.print("readUriPermissions="); pw.println(readUriPermissions); - } - if (writeUriPermissions != null) { - pw.print(prefix); pw.print("writeUriPermissions="); pw.println(writeUriPermissions); + if (uriPermissions != null) { + if (uriPermissions.readUriPermissions != null) { + pw.print(prefix); pw.print("readUriPermissions="); + pw.println(uriPermissions.readUriPermissions); + } + if (uriPermissions.writeUriPermissions != null) { + pw.print(prefix); pw.print("writeUriPermissions="); + pw.println(uriPermissions.writeUriPermissions); + } } pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed); pw.print(" haveState="); pw.print(haveState); @@ -301,6 +304,13 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne } } + UriPermissionOwner getUriPermissionsLocked() { + if (uriPermissions == null) { + uriPermissions = new UriPermissionOwner(service, this); + } + return uriPermissions; + } + void addResultLocked(ActivityRecord from, String resultWho, int requestCode, int resultCode, Intent resultData) { @@ -350,7 +360,7 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne intent = new Intent(intent); ar.add(intent); service.grantUriPermissionFromIntentLocked(callingUid, packageName, - intent, this); + intent, getUriPermissionsLocked()); app.thread.scheduleNewIntent(ar, this); sent = true; } catch (RemoteException e) { @@ -367,27 +377,9 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne } void removeUriPermissionsLocked() { - if (readUriPermissions != null) { - for (UriPermission perm : readUriPermissions) { - perm.readOwners.remove(this); - if (perm.readOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; - service.removeUriPermissionIfNeededLocked(perm); - } - } - readUriPermissions = null; - } - if (writeUriPermissions != null) { - for (UriPermission perm : writeUriPermissions) { - perm.writeOwners.remove(this); - if (perm.writeOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; - service.removeUriPermissionIfNeededLocked(perm); - } - } - writeUriPermissions = null; + if (uriPermissions != null) { + uriPermissions.removeUriPermissionsLocked(); + uriPermissions = null; } } @@ -578,38 +570,6 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne state == ActivityState.RESUMED; } - @Override - public void addReadPermission(UriPermission perm) { - if (readUriPermissions == null) { - readUriPermissions = new HashSet<UriPermission>(); - } - readUriPermissions.add(perm); - } - - @Override - public void addWritePermission(UriPermission perm) { - if (writeUriPermissions == null) { - writeUriPermissions = new HashSet<UriPermission>(); - } - writeUriPermissions.add(perm); - } - - @Override - public void removeReadPermission(UriPermission perm) { - readUriPermissions.remove(perm); - if (readUriPermissions.size() == 0) { - readUriPermissions = null; - } - } - - @Override - public void removeWritePermission(UriPermission perm) { - writeUriPermissions.remove(perm); - if (writeUriPermissions.size() == 0) { - writeUriPermissions = null; - } - } - public String toString() { if (stringName != null) { return stringName; diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index a5f7e96..a99b48c 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -2327,12 +2327,12 @@ public class ActivityStack { if (grantedUriPermissions != null && callingUid > 0) { for (int i=0; i<grantedUriPermissions.length; i++) { mService.grantUriPermissionLocked(callingUid, r.packageName, - grantedUriPermissions[i], grantedMode, r); + grantedUriPermissions[i], grantedMode, r.getUriPermissionsLocked()); } } mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, - intent, r); + intent, r.getUriPermissionsLocked()); if (newTask) { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId); @@ -2557,7 +2557,7 @@ public class ActivityStack { if (callingUid > 0) { mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, - data, r); + data, r.getUriPermissionsLocked()); } if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r @@ -2885,7 +2885,7 @@ public class ActivityStack { + " res=" + resultCode + " data=" + resultData); if (r.info.applicationInfo.uid > 0) { mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid, - r.packageName, resultData, r); + r.packageName, resultData, r.getUriPermissionsLocked()); } resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, resultData); diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java index d5b050b..f35a68e 100644 --- a/services/java/com/android/server/am/ServiceRecord.java +++ b/services/java/com/android/server/am/ServiceRecord.java @@ -96,7 +96,7 @@ class ServiceRecord extends Binder { String stringName; // caching of toString - static class StartItem implements UriPermissionOwner { + static class StartItem { final ServiceRecord sr; final int id; final Intent intent; @@ -104,12 +104,10 @@ class ServiceRecord extends Binder { long deliveredTime; int deliveryCount; int doneExecutingCount; + UriPermissionOwner uriPermissions; String stringName; // caching of toString - HashSet<UriPermission> readUriPermissions; // special access to reading uris. - HashSet<UriPermission> writeUriPermissions; // special access to writing uris. - StartItem(ServiceRecord _sr, int _id, Intent _intent, int _targetPermissionUid) { sr = _sr; id = _id; @@ -117,60 +115,17 @@ class ServiceRecord extends Binder { targetPermissionUid = _targetPermissionUid; } - void removeUriPermissionsLocked() { - if (readUriPermissions != null) { - for (UriPermission perm : readUriPermissions) { - perm.readOwners.remove(this); - if (perm.readOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; - sr.ams.removeUriPermissionIfNeededLocked(perm); - } - } - readUriPermissions = null; - } - if (writeUriPermissions != null) { - for (UriPermission perm : writeUriPermissions) { - perm.writeOwners.remove(this); - if (perm.writeOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; - sr.ams.removeUriPermissionIfNeededLocked(perm); - } - } - writeUriPermissions = null; - } - } - - @Override - public void addReadPermission(UriPermission perm) { - if (readUriPermissions == null) { - readUriPermissions = new HashSet<UriPermission>(); + UriPermissionOwner getUriPermissionsLocked() { + if (uriPermissions == null) { + uriPermissions = new UriPermissionOwner(sr.ams, this); } - readUriPermissions.add(perm); + return uriPermissions; } - @Override - public void addWritePermission(UriPermission perm) { - if (writeUriPermissions == null) { - writeUriPermissions = new HashSet<UriPermission>(); - } - writeUriPermissions.add(perm); - } - - @Override - public void removeReadPermission(UriPermission perm) { - readUriPermissions.remove(perm); - if (readUriPermissions.size() == 0) { - readUriPermissions = null; - } - } - - @Override - public void removeWritePermission(UriPermission perm) { - writeUriPermissions.remove(perm); - if (writeUriPermissions.size() == 0) { - writeUriPermissions = null; + void removeUriPermissionsLocked() { + if (uriPermissions != null) { + uriPermissions.removeUriPermissionsLocked(); + uriPermissions = null; } } @@ -218,13 +173,15 @@ class ServiceRecord extends Binder { pw.print(prefix); pw.print(" targetPermissionUid="); pw.println(si.targetPermissionUid); } - if (si.readUriPermissions != null) { - pw.print(prefix); pw.print(" readUriPermissions="); - pw.println(si.readUriPermissions); - } - if (si.writeUriPermissions != null) { - pw.print(prefix); pw.print(" writeUriPermissions="); - pw.println(si.writeUriPermissions); + if (si.uriPermissions != null) { + if (si.uriPermissions.readUriPermissions != null) { + pw.print(prefix); pw.print(" readUriPermissions="); + pw.println(si.uriPermissions.readUriPermissions); + } + if (si.uriPermissions.writeUriPermissions != null) { + pw.print(prefix); pw.print(" writeUriPermissions="); + pw.println(si.uriPermissions.writeUriPermissions); + } } } } diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java index 93c59cc..c95546e 100644 --- a/services/java/com/android/server/am/UriPermission.java +++ b/services/java/com/android/server/am/UriPermission.java @@ -22,13 +22,14 @@ import android.net.Uri; import java.io.PrintWriter; import java.util.HashSet; -interface UriPermissionOwner { - void addReadPermission(UriPermission perm); - void addWritePermission(UriPermission perm); - void removeReadPermission(UriPermission perm); - void removeWritePermission(UriPermission perm); -} - +/** + * Description of a permission granted to an app to access a particular URI. + * + * CTS tests for this functionality can be run with "runtest cts-appsecurity". + * + * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert + * /src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java + */ class UriPermission { final int uid; final Uri uri; diff --git a/services/java/com/android/server/am/UriPermissionOwner.java b/services/java/com/android/server/am/UriPermissionOwner.java new file mode 100644 index 0000000..99c82e6 --- /dev/null +++ b/services/java/com/android/server/am/UriPermissionOwner.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2010 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 com.android.server.am; + +import android.content.Intent; +import android.net.Uri; +import android.os.Binder; +import android.os.IBinder; + +import java.util.HashSet; +import java.util.Iterator; + +class UriPermissionOwner { + final ActivityManagerService service; + final Object owner; + + Binder externalToken; + + HashSet<UriPermission> readUriPermissions; // special access to reading uris. + HashSet<UriPermission> writeUriPermissions; // special access to writing uris. + + class ExternalToken extends Binder { + UriPermissionOwner getOwner() { + return UriPermissionOwner.this; + } + } + + UriPermissionOwner(ActivityManagerService _service, Object _owner) { + service = _service; + owner = _owner; + } + + Binder getExternalTokenLocked() { + if (externalToken != null) { + externalToken = new ExternalToken(); + } + return externalToken; + } + + static UriPermissionOwner fromExternalToken(IBinder token) { + if (token instanceof ExternalToken) { + return ((ExternalToken)token).getOwner(); + } + return null; + } + + void removeUriPermissionsLocked() { + removeUriPermissionsLocked(Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + } + + void removeUriPermissionsLocked(int mode) { + if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 + && readUriPermissions != null) { + for (UriPermission perm : readUriPermissions) { + perm.readOwners.remove(this); + if (perm.readOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + } + readUriPermissions = null; + } + if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 + && writeUriPermissions != null) { + for (UriPermission perm : writeUriPermissions) { + perm.writeOwners.remove(this); + if (perm.writeOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + } + writeUriPermissions = null; + } + } + + void removeUriPermissionLocked(Uri uri, int mode) { + if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 + && readUriPermissions != null) { + Iterator<UriPermission> it = readUriPermissions.iterator(); + while (it.hasNext()) { + UriPermission perm = it.next(); + if (uri.equals(perm.uri)) { + perm.readOwners.remove(this); + if (perm.readOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + it.remove(); + } + } + if (readUriPermissions.size() == 0) { + readUriPermissions = null; + } + } + if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 + && writeUriPermissions != null) { + Iterator<UriPermission> it = writeUriPermissions.iterator(); + while (it.hasNext()) { + UriPermission perm = it.next(); + if (uri.equals(perm.uri)) { + perm.writeOwners.remove(this); + if (perm.writeOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + it.remove(); + } + } + if (writeUriPermissions.size() == 0) { + writeUriPermissions = null; + } + } + } + + public void addReadPermission(UriPermission perm) { + if (readUriPermissions == null) { + readUriPermissions = new HashSet<UriPermission>(); + } + readUriPermissions.add(perm); + } + + public void addWritePermission(UriPermission perm) { + if (writeUriPermissions == null) { + writeUriPermissions = new HashSet<UriPermission>(); + } + writeUriPermissions.add(perm); + } + + public void removeReadPermission(UriPermission perm) { + readUriPermissions.remove(perm); + if (readUriPermissions.size() == 0) { + readUriPermissions = null; + } + } + + public void removeWritePermission(UriPermission perm) { + writeUriPermissions.remove(perm); + if (writeUriPermissions.size() == 0) { + writeUriPermissions = null; + } + } + + @Override + public String toString() { + return owner.toString(); + } +} |