am 39792d22: Fix bugs with granting permissions through onNewIntent().

Merge commit '39792d2262352ae775091876d5488d2412a2ff92' into gingerbread-plus-aosp

* commit '39792d2262352ae775091876d5488d2412a2ff92':
  Fix bugs with granting permissions through onNewIntent().
This commit is contained in:
Dianne Hackborn
2010-08-20 11:53:29 -07:00
committed by Android Git Automerger
7 changed files with 357 additions and 156 deletions

View File

@ -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);

View File

@ -4096,16 +4096,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();
@ -4113,7 +4120,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();
@ -4130,7 +4137,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;
@ -4139,10 +4146,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?
@ -4150,7 +4157,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?
@ -4187,12 +4194,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<Uri, UriPermission> targetUris
= mGrantedUriPermissions.get(targetUid);
@ -4208,39 +4226,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<UriPermission>();
}
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<UriPermission>();
}
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,
@ -8211,18 +8255,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;
@ -8236,10 +8285,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.
@ -8249,14 +8294,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,
@ -8339,7 +8376,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);
@ -8359,6 +8396,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
@ -8598,7 +8636,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) {
@ -8658,6 +8696,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);
@ -8668,7 +8708,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();
@ -8793,7 +8834,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;
}
}

View File

@ -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<Intent> ar = new ArrayList<Intent>();
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<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) {

View File

@ -2033,16 +2033,6 @@ 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);
}
}
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
intent, r);
if (sourceRecord == null) {
// This activity is not being started from another... in this
// case we -always- start a new task.
@ -2150,7 +2140,7 @@ public class ActivityStack {
top.task.setIntent(r.intent, r.info);
}
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
top.deliverNewIntentLocked(r.intent);
top.deliverNewIntentLocked(callingUid, r.intent);
} else {
// A special case: we need to
// start the activity because it is not currently
@ -2175,7 +2165,7 @@ public class ActivityStack {
if (taskTop.frontOfTask) {
taskTop.task.setIntent(r.intent, r.info);
}
taskTop.deliverNewIntentLocked(r.intent);
taskTop.deliverNewIntentLocked(callingUid, r.intent);
} else if (!r.intent.filterEquals(taskTop.task.intent)) {
// In this case we are launching the root activity
// of the task, but with a different intent. We
@ -2243,7 +2233,7 @@ public class ActivityStack {
// is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
top.deliverNewIntentLocked(r.intent);
top.deliverNewIntentLocked(callingUid, r.intent);
return START_DELIVERED_TO_TOP;
}
}
@ -2288,7 +2278,7 @@ public class ActivityStack {
sourceRecord.task.taskId, r, launchFlags, true);
if (top != null) {
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
top.deliverNewIntentLocked(r.intent);
top.deliverNewIntentLocked(callingUid, r.intent);
// For paranoia, make sure we have correctly
// resumed the top activity.
if (doResume) {
@ -2305,7 +2295,7 @@ public class ActivityStack {
if (where >= 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<grantedUriPermissions.length; i++) {
mService.grantUriPermissionLocked(callingUid, r.packageName,
grantedUriPermissions[i], grantedMode, r);
}
}
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
intent, r);
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
}

View File

@ -26,6 +26,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.PrintWriterPrinter;
import android.util.TimeUtils;
import java.io.PrintWriter;
import java.util.List;
@ -73,61 +74,65 @@ class BroadcastRecord extends Binder {
ActivityInfo curReceiver; // info about the receiver that is currently running.
void dump(PrintWriter pw, String prefix) {
pw.println(prefix + this);
pw.println(prefix + intent);
final long now = SystemClock.uptimeMillis();
pw.print(prefix); pw.println(this);
pw.print(prefix); pw.println(intent);
if (sticky) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
pw.println(prefix + "extras: " + bundle.toString());
pw.print(prefix); pw.print("extras: "); pw.println(bundle.toString());
}
}
pw.println(prefix + "proc=" + callerApp);
pw.println(prefix + "caller=" + callerPackage
+ " callingPid=" + callingPid
+ " callingUid=" + callingUid);
pw.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.println(" ");
pw.println(callerApp != null ? callerApp.toShortString() : "null");
pw.print(" pid="); pw.print(callingPid);
pw.print(" uid="); pw.println(callingUid);
if (requiredPermission != null) {
pw.println(prefix + "requiredPermission=" + requiredPermission);
pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission);
}
pw.println(prefix + "dispatchTime=" + dispatchTime + " ("
+ (SystemClock.uptimeMillis()-dispatchTime) + "ms since now)");
pw.print(prefix); pw.print("dispatchTime=");
TimeUtils.formatDuration(dispatchTime, now, pw);
if (finishTime != 0) {
pw.println(prefix + "finishTime=" + finishTime + " ("
+ (SystemClock.uptimeMillis()-finishTime) + "ms since now)");
pw.print(" finishTime="); TimeUtils.formatDuration(finishTime, now, pw);
} else {
pw.println(prefix + "receiverTime=" + receiverTime + " ("
+ (SystemClock.uptimeMillis()-receiverTime) + "ms since now)");
pw.print(" receiverTime="); TimeUtils.formatDuration(receiverTime, now, pw);
}
pw.println("");
if (anrCount != 0) {
pw.println(prefix + "anrCount=" + anrCount);
pw.print(prefix); pw.print("anrCount="); pw.println(anrCount);
}
if (resultTo != null || resultCode != -1 || resultData != null) {
pw.println(prefix + "resultTo=" + resultTo
+ " resultCode=" + resultCode + " resultData=" + resultData);
pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
pw.print(" resultCode="); pw.print(resultCode);
pw.print(" resultData="); pw.println(resultData);
}
if (resultExtras != null) {
pw.println(prefix + "resultExtras=" + resultExtras);
pw.print(prefix); pw.print("resultExtras="); pw.println(resultExtras);
}
if (resultAbort || ordered || sticky || initialSticky) {
pw.println(prefix + "resultAbort=" + resultAbort
+ " ordered=" + ordered + " sticky=" + sticky
+ " initialSticky=" + initialSticky);
pw.print(prefix); pw.print("resultAbort="); pw.print(resultAbort);
pw.print(" ordered="); pw.print(ordered);
pw.print(" sticky="); pw.print(sticky);
pw.print(" initialSticky="); pw.println(initialSticky);
}
if (nextReceiver != 0 || receiver != null) {
pw.println(prefix + "nextReceiver=" + nextReceiver
+ " receiver=" + receiver);
pw.print(prefix); pw.print("nextReceiver="); pw.print(nextReceiver);
pw.print(" receiver="); pw.println(receiver);
}
if (curFilter != null) {
pw.println(prefix + "curFilter=" + curFilter);
pw.print(prefix); pw.print("curFilter="); pw.println(curFilter);
}
if (curReceiver != null) {
pw.println(prefix + "curReceiver=" + curReceiver);
pw.print(prefix); pw.print("curReceiver="); pw.println(curReceiver);
}
if (curApp != null) {
pw.println(prefix + "curApp=" + curApp);
pw.println(prefix + "curComponent="
+ (curComponent != null ? curComponent.toShortString() : "--"));
pw.print(prefix); pw.print("curApp="); pw.println(curApp);
pw.print(prefix); pw.print("curComponent=");
pw.println((curComponent != null ? curComponent.toShortString() : "--"));
if (curReceiver != null && curReceiver.applicationInfo != null) {
pw.println(prefix + "curSourceDir=" + curReceiver.applicationInfo.sourceDir);
pw.print(prefix); pw.print("curSourceDir=");
pw.println(curReceiver.applicationInfo.sourceDir);
}
}
String stateStr = " (?)";
@ -137,13 +142,14 @@ class BroadcastRecord extends Binder {
case CALL_IN_RECEIVE: stateStr=" (CALL_IN_RECEIVE)"; break;
case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break;
}
pw.println(prefix + "state=" + state + stateStr);
pw.print(prefix); pw.print("state="); pw.print(state); pw.println(stateStr);
final int N = receivers != null ? receivers.size() : 0;
String p2 = prefix + " ";
PrintWriterPrinter printer = new PrintWriterPrinter(pw);
for (int i=0; i<N; i++) {
Object o = receivers.get(i);
pw.println(prefix + "Receiver #" + i + ": " + o);
pw.print(prefix); pw.print("Receiver #"); pw.print(i);
pw.print(": "); pw.println(o);
if (o instanceof BroadcastFilter)
((BroadcastFilter)o).dumpBrief(pw, p2);
else if (o instanceof ResolveInfo)

View File

@ -36,6 +36,7 @@ import android.util.TimeUtils;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@ -43,6 +44,12 @@ import java.util.List;
* A running application service.
*/
class ServiceRecord extends Binder {
// 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;
final ActivityManagerService ams;
final BatteryStatsImpl.Uid.Pkg.Serv stats;
final ComponentName name; // service component.
@ -68,29 +75,6 @@ class ServiceRecord extends Binder {
final HashMap<IBinder, ConnectionRecord> connections
= new HashMap<IBinder, ConnectionRecord>();
// 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<StartItem> deliveredStarts = new ArrayList<StartItem>();
// start() arguments which been delivered.
final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>();
// 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<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;
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<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;
}
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<StartItem> deliveredStarts = new ArrayList<StartItem>();
// start() arguments which been delivered.
final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>();
// start() arguments that haven't yet been delivered.
void dumpStartList(PrintWriter pw, String prefix, List<StartItem> list, long now) {
final int N = list.size();
for (int i=0; i<N; i++) {
@ -128,9 +210,22 @@ class ServiceRecord extends Binder {
if (si.doneExecutingCount != 0) {
pw.print(" dxc="); pw.print(si.doneExecutingCount);
}
pw.print(" ");
pw.println("");
pw.print(prefix); pw.print(" intent=");
if (si.intent != null) pw.println(si.intent.toString());
else pw.println("null");
if (si.targetPermissionUid >= 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;

View File

@ -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<ActivityRecord> readActivities = new HashSet<ActivityRecord>();
final HashSet<ActivityRecord> writeActivities = new HashSet<ActivityRecord>();
final HashSet<UriPermissionOwner> readOwners = new HashSet<UriPermissionOwner>();
final HashSet<UriPermissionOwner> writeOwners = new HashSet<UriPermissionOwner>();
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);
}
}
}
}