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:
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user