Fix bugs with granting permissions through onNewIntent().
It would grant the permission to the temporary ActivityRecord, not the real one, so it never got cleaned up. Also allow granting of permissions to services because... well, it would be really really useful. And it introduces some refactoring that we'll need to support cut/paste. Change-Id: If521f509042e7baad7f5dc9bec84b6ba0d90ba09
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);
|
||||
|
@ -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<Uri, UriPermission> 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<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,
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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