diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 7901b155467aa..244d126b89bb2 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -389,15 +389,17 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { if (permission != null) { pw.println(prefix + "permission=" + permission); } - pw.println(prefix + "uid=" + uid + " taskAffinity=" + taskAffinity); - if (theme != 0) { - pw.println(prefix + "theme=0x" + Integer.toHexString(theme)); - } - pw.println(prefix + "flags=0x" + Integer.toHexString(flags) - + " processName=" + processName); + pw.println(prefix + "processName=" + processName); + pw.println(prefix + "taskAffinity=" + taskAffinity); + pw.println(prefix + "uid=" + uid + " flags=0x" + Integer.toHexString(flags) + + " theme=0x" + Integer.toHexString(theme)); pw.println(prefix + "sourceDir=" + sourceDir); - pw.println(prefix + "publicSourceDir=" + publicSourceDir); - pw.println(prefix + "resourceDirs=" + resourceDirs); + if (!sourceDir.equals(publicSourceDir)) { + pw.println(prefix + "publicSourceDir=" + publicSourceDir); + } + if (resourceDirs != null) { + pw.println(prefix + "resourceDirs=" + resourceDirs); + } pw.println(prefix + "dataDir=" + dataDir); if (sharedLibraryFiles != null) { pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 9d31502fbca4a..b37cd89897454 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -4093,16 +4093,23 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - void grantUriPermissionLocked(int callingUid, - String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) { + /** + * Check if the targetPkg can be granted permission to access uri by + * the callingUid using the given modeFlags. Throws a security exception + * if callingUid is not allowed to do this. Returns the uid of the target + * if the URI permission grant should be performed; returns -1 if it is not + * needed (for example targetPkg already has permission to access the URI). + */ + int checkGrantUriPermissionLocked(int callingUid, String targetPkg, + Uri uri, int modeFlags) { modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); if (modeFlags == 0) { - return; + return -1; } if (DEBUG_URI_PERMISSION) Slog.v(TAG, - "Requested grant " + targetPkg + " permission to " + uri); + "Checking grant " + targetPkg + " permission to " + uri); final IPackageManager pm = AppGlobals.getPackageManager(); @@ -4110,7 +4117,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) { if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Can't grant URI permission for non-content URI: " + uri); - return; + return -1; } String name = uri.getAuthority(); @@ -4127,7 +4134,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } if (pi == null) { Slog.w(TAG, "No content provider found for: " + name); - return; + return -1; } int targetUid; @@ -4136,10 +4143,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (targetUid < 0) { if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Can't grant URI permission no uid for: " + targetPkg); - return; + return -1; } } catch (RemoteException ex) { - return; + return -1; } // First... does the target actually need this permission? @@ -4147,7 +4154,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // No need to grant the target this permission. if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Target " + targetPkg + " already has full permission to " + uri); - return; + return -1; } // Second... is the provider allowing granting of URI permissions? @@ -4184,12 +4191,23 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - // Okay! So here we are: the caller has the assumed permission + return targetUid; + } + + void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg, + Uri uri, int modeFlags, UriPermissionOwner owner) { + modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + if (modeFlags == 0) { + return; + } + + // So here we are: the caller has the assumed permission // to the uri, and the target doesn't. Let's now give this to // the target. if (DEBUG_URI_PERMISSION) Slog.v(TAG, - "Granting " + targetPkg + " permission to " + uri); + "Granting " + targetPkg + "/" + targetUid + " permission to " + uri); HashMap targetUris = mGrantedUriPermissions.get(targetUid); @@ -4205,39 +4223,65 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } perm.modeFlags |= modeFlags; - if (activity == null) { + if (owner == null) { perm.globalModeFlags |= modeFlags; } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { - perm.readActivities.add(activity); - if (activity.readUriPermissions == null) { - activity.readUriPermissions = new HashSet(); - } - activity.readUriPermissions.add(perm); + perm.readOwners.add(owner); + owner.addReadPermission(perm); } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) { - perm.writeActivities.add(activity); - if (activity.writeUriPermissions == null) { - activity.writeUriPermissions = new HashSet(); - } - activity.writeUriPermissions.add(perm); + perm.writeOwners.add(owner); + owner.addWritePermission(perm); } } - void grantUriPermissionFromIntentLocked(int callingUid, - String targetPkg, Intent intent, ActivityRecord activity) { + void grantUriPermissionLocked(int callingUid, + String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) { + int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags); + if (targetUid < 0) { + return; + } + + grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner); + } + + /** + * Like checkGrantUriPermissionLocked, but takes an Intent. + */ + int checkGrantUriPermissionFromIntentLocked(int callingUid, + String targetPkg, Intent intent) { if (DEBUG_URI_PERMISSION) Slog.v(TAG, - "Grant URI perm to " + (intent != null ? intent.getData() : null) + "Checking URI perm to " + (intent != null ? intent.getData() : null) + " from " + intent + "; flags=0x" + Integer.toHexString(intent != null ? intent.getFlags() : 0)); if (intent == null) { - return; + return -1; } Uri data = intent.getData(); if (data == null) { + return -1; + } + return checkGrantUriPermissionLocked(callingUid, targetPkg, data, + intent.getFlags()); + } + + /** + * Like grantUriPermissionUncheckedLocked, but takes an Intent. + */ + void grantUriPermissionUncheckedFromIntentLocked(int targetUid, + String targetPkg, Intent intent, UriPermissionOwner owner) { + grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(), + intent.getFlags(), owner); + } + + void grantUriPermissionFromIntentLocked(int callingUid, + String targetPkg, Intent intent, UriPermissionOwner owner) { + int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent); + if (targetUid < 0) { return; } - grantUriPermissionLocked(callingUid, targetPkg, data, - intent.getFlags(), activity); + + grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner); } public void grantUriPermission(IApplicationThread caller, String targetPkg, @@ -8187,18 +8231,23 @@ public final class ActivityManagerService extends ActivityManagerNative implemen return; } - int i = 0; - while (i < N) { + while (r.pendingStarts.size() > 0) { try { - ServiceRecord.StartItem si = r.pendingStarts.get(i); + ServiceRecord.StartItem si = r.pendingStarts.remove(0); if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: " + r.name + " " + r.intent + " args=" + si.intent); - if (si.intent == null && N > 1) { + if (si.intent == null) { // If somehow we got a dummy start at the front, then // just drop it here. - i++; continue; } + si.deliveredTime = SystemClock.uptimeMillis(); + r.deliveredStarts.add(si); + si.deliveryCount++; + if (si.targetPermissionUid >= 0) { + grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid, + r.packageName, si.intent, si); + } bumpServiceExecutingLocked(r); if (!oomAdjusted) { oomAdjusted = true; @@ -8212,10 +8261,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen flags |= Service.START_FLAG_REDELIVERY; } r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent); - si.deliveredTime = SystemClock.uptimeMillis(); - r.deliveredStarts.add(si); - si.deliveryCount++; - i++; } catch (RemoteException e) { // Remote process gone... we'll let the normal cleanup take // care of this. @@ -8225,14 +8270,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen break; } } - if (i == N) { - r.pendingStarts.clear(); - } else { - while (i > 0) { - i--; - r.pendingStarts.remove(i); - } - } } private final boolean requestServiceBindingLocked(ServiceRecord r, @@ -8315,7 +8352,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (r.lastStartId < 1) { r.lastStartId = 1; } - r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null)); + r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1)); } sendServiceArgsLocked(r, true); @@ -8335,6 +8372,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (N > 0) { for (int i=N-1; i>=0; i--) { ServiceRecord.StartItem si = r.deliveredStarts.get(i); + si.removeUriPermissionsLocked(); if (si.intent == null) { // We'll generate this again if needed. } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT @@ -8574,7 +8612,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen r.foregroundNoti = null; // Clear start entries. - r.deliveredStarts.clear(); + r.clearDeliveredStartsLocked(); r.pendingStarts.clear(); if (r.app != null) { @@ -8634,6 +8672,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen ? res.permission : "private to package"); } ServiceRecord r = res.record; + int targetPermissionUid = checkGrantUriPermissionFromIntentLocked( + callingUid, r.packageName, service); if (unscheduleServiceRestartLocked(r)) { if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r.shortName); @@ -8644,7 +8684,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (r.lastStartId < 1) { r.lastStartId = 1; } - r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service)); + r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, + service, targetPermissionUid)); r.lastActivity = SystemClock.uptimeMillis(); synchronized (r.stats.getBatteryStats()) { r.stats.startRunningLocked(); @@ -8769,7 +8810,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen ServiceRecord.StartItem si = r.findDeliveredStart(startId, false); if (si != null) { while (r.deliveredStarts.size() > 0) { - if (r.deliveredStarts.remove(0) == si) { + ServiceRecord.StartItem cur = r.deliveredStarts.remove(0); + cur.removeUriPermissionsLocked(); + if (cur == si) { break; } } diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 79756a7af272e..80a41b7fb31b7 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -29,6 +29,7 @@ import android.graphics.Bitmap; import android.os.Bundle; import android.os.Message; import android.os.Process; +import android.os.RemoteException; import android.os.SystemClock; import android.util.EventLog; import android.util.Log; @@ -43,7 +44,7 @@ import java.util.HashSet; /** * An entry in the history stack, representing an activity. */ -class ActivityRecord extends IApplicationToken.Stub { +class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwner { final ActivityManagerService service; // owner final ActivityStack stack; // owner final ActivityInfo info; // all about me @@ -340,16 +341,22 @@ class ActivityRecord extends IApplicationToken.Stub { * Deliver a new Intent to an existing activity, so that its onNewIntent() * method will be called at the proper time. */ - final void deliverNewIntentLocked(Intent intent) { + final void deliverNewIntentLocked(int callingUid, Intent intent) { boolean sent = false; if (state == ActivityState.RESUMED && app != null && app.thread != null) { try { ArrayList ar = new ArrayList(); - ar.add(new Intent(intent)); + intent = new Intent(intent); + ar.add(intent); + service.grantUriPermissionFromIntentLocked(callingUid, packageName, + intent, this); app.thread.scheduleNewIntent(ar, this); sent = true; - } catch (Exception e) { + } catch (RemoteException e) { + Slog.w(ActivityManagerService.TAG, + "Exception thrown sending new intent to " + this, e); + } catch (NullPointerException e) { Slog.w(ActivityManagerService.TAG, "Exception thrown sending new intent to " + this, e); } @@ -362,23 +369,25 @@ class ActivityRecord extends IApplicationToken.Stub { void removeUriPermissionsLocked() { if (readUriPermissions != null) { for (UriPermission perm : readUriPermissions) { - perm.readActivities.remove(this); - if (perm.readActivities.size() == 0 && (perm.globalModeFlags + 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); + service.removeUriPermissionIfNeededLocked(perm); } } + readUriPermissions = null; } if (writeUriPermissions != null) { for (UriPermission perm : writeUriPermissions) { - perm.writeActivities.remove(this); - if (perm.writeActivities.size() == 0 && (perm.globalModeFlags + 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; } } @@ -569,6 +578,37 @@ class ActivityRecord extends IApplicationToken.Stub { state == ActivityState.RESUMED; } + @Override + public void addReadPermission(UriPermission perm) { + if (readUriPermissions == null) { + readUriPermissions = new HashSet(); + } + readUriPermissions.add(perm); + } + + @Override + public void addWritePermission(UriPermission perm) { + if (writeUriPermissions == null) { + writeUriPermissions = new HashSet(); + } + 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) { diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index de7b15cc0091f..a5f7e96866fe3 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -2033,16 +2033,6 @@ public class ActivityStack { } } - if (grantedUriPermissions != null && callingUid > 0) { - for (int i=0; i= 0) { ActivityRecord top = moveActivityToFrontLocked(where); logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); - top.deliverNewIntentLocked(r.intent); + top.deliverNewIntentLocked(callingUid, r.intent); if (doResume) { resumeTopActivityLocked(null); } @@ -2333,6 +2323,17 @@ public class ActivityStack { if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new guessed " + r.task); } + + if (grantedUriPermissions != null && callingUid > 0) { + for (int i=0; i connections = new HashMap(); // IBinder -> ConnectionRecord of all bound clients - - // Maximum number of delivery attempts before giving up. - static final int MAX_DELIVERY_COUNT = 3; - - // Maximum number of times it can fail during execution before giving up. - static final int MAX_DONE_EXECUTING_COUNT = 6; - - static class StartItem { - final int id; - final Intent intent; - long deliveredTime; - int deliveryCount; - int doneExecutingCount; - - StartItem(int _id, Intent _intent) { - id = _id; - intent = _intent; - } - } - final ArrayList deliveredStarts = new ArrayList(); - // start() arguments which been delivered. - final ArrayList pendingStarts = new ArrayList(); - // start() arguments that haven't yet been delivered. ProcessRecord app; // where this service is running or null. boolean isForeground; // is service currently in foreground mode? @@ -112,6 +96,104 @@ class ServiceRecord extends Binder { String stringName; // caching of toString + static class StartItem implements UriPermissionOwner { + final ServiceRecord sr; + final int id; + final Intent intent; + final int targetPermissionUid; + long deliveredTime; + int deliveryCount; + int doneExecutingCount; + + String stringName; // caching of toString + + HashSet readUriPermissions; // special access to reading uris. + HashSet writeUriPermissions; // special access to writing uris. + + StartItem(ServiceRecord _sr, int _id, Intent _intent, int _targetPermissionUid) { + sr = _sr; + id = _id; + intent = _intent; + 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(); + } + readUriPermissions.add(perm); + } + + @Override + public void addWritePermission(UriPermission perm) { + if (writeUriPermissions == null) { + writeUriPermissions = new HashSet(); + } + 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; + } + StringBuilder sb = new StringBuilder(128); + sb.append("ServiceRecord{") + .append(Integer.toHexString(System.identityHashCode(sr))) + .append(' ').append(sr.shortName) + .append(" StartItem ") + .append(Integer.toHexString(System.identityHashCode(this))) + .append(" id=").append(id).append('}'); + return stringName = sb.toString(); + } + } + + final ArrayList deliveredStarts = new ArrayList(); + // start() arguments which been delivered. + final ArrayList pendingStarts = new ArrayList(); + // start() arguments that haven't yet been delivered. + void dumpStartList(PrintWriter pw, String prefix, List list, long now) { final int N = list.size(); for (int i=0; i= 0) { + 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); + } } } @@ -324,6 +419,13 @@ class ServiceRecord extends Binder { } } + public void clearDeliveredStartsLocked() { + for (int i=deliveredStarts.size()-1; i>=0; i--) { + deliveredStarts.get(i).removeUriPermissionsLocked(); + } + deliveredStarts.clear(); + } + public String toString() { if (stringName != null) { return stringName; diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java index 81450c5758f8b..93c59cc1dd990 100644 --- a/services/java/com/android/server/am/UriPermission.java +++ b/services/java/com/android/server/am/UriPermission.java @@ -22,13 +22,20 @@ 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); +} + class UriPermission { final int uid; final Uri uri; int modeFlags = 0; int globalModeFlags = 0; - final HashSet readActivities = new HashSet(); - final HashSet writeActivities = new HashSet(); + final HashSet readOwners = new HashSet(); + final HashSet writeOwners = new HashSet(); String stringName; @@ -41,27 +48,21 @@ class UriPermission { if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; - if (readActivities.size() > 0) { - for (ActivityRecord r : readActivities) { - r.readUriPermissions.remove(this); - if (r.readUriPermissions.size() == 0) { - r.readUriPermissions = null; - } + if (readOwners.size() > 0) { + for (UriPermissionOwner r : readOwners) { + r.removeReadPermission(this); } - readActivities.clear(); + readOwners.clear(); } } if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) { globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; - if (readActivities.size() > 0) { - for (ActivityRecord r : readActivities) { - r.writeUriPermissions.remove(this); - if (r.writeUriPermissions.size() == 0) { - r.writeUriPermissions = null; - } + if (readOwners.size() > 0) { + for (UriPermissionOwner r : writeOwners) { + r.removeWritePermission(this); } - readActivities.clear(); + readOwners.clear(); } } } @@ -85,11 +86,17 @@ class UriPermission { pw.print(" uid="); pw.print(uid); pw.print(" globalModeFlags=0x"); pw.println(Integer.toHexString(globalModeFlags)); - if (readActivities.size() != 0) { - pw.print(prefix); pw.print("readActivities="); pw.println(readActivities); + if (readOwners.size() != 0) { + pw.print(prefix); pw.println("readOwners:"); + for (UriPermissionOwner owner : readOwners) { + pw.print(prefix); pw.print(" * "); pw.println(owner); + } } - if (writeActivities.size() != 0) { - pw.print(prefix); pw.print("writeActivities="); pw.println(writeActivities); + if (writeOwners.size() != 0) { + pw.print(prefix); pw.println("writeOwners:"); + for (UriPermissionOwner owner : writeOwners) { + pw.print(prefix); pw.print(" * "); pw.println(owner); + } } } }