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) {
|
if (permission != null) {
|
||||||
pw.println(prefix + "permission=" + permission);
|
pw.println(prefix + "permission=" + permission);
|
||||||
}
|
}
|
||||||
pw.println(prefix + "uid=" + uid + " taskAffinity=" + taskAffinity);
|
pw.println(prefix + "processName=" + processName);
|
||||||
if (theme != 0) {
|
pw.println(prefix + "taskAffinity=" + taskAffinity);
|
||||||
pw.println(prefix + "theme=0x" + Integer.toHexString(theme));
|
pw.println(prefix + "uid=" + uid + " flags=0x" + Integer.toHexString(flags)
|
||||||
}
|
+ " theme=0x" + Integer.toHexString(theme));
|
||||||
pw.println(prefix + "flags=0x" + Integer.toHexString(flags)
|
|
||||||
+ " processName=" + processName);
|
|
||||||
pw.println(prefix + "sourceDir=" + sourceDir);
|
pw.println(prefix + "sourceDir=" + sourceDir);
|
||||||
|
if (!sourceDir.equals(publicSourceDir)) {
|
||||||
pw.println(prefix + "publicSourceDir=" + publicSourceDir);
|
pw.println(prefix + "publicSourceDir=" + publicSourceDir);
|
||||||
|
}
|
||||||
|
if (resourceDirs != null) {
|
||||||
pw.println(prefix + "resourceDirs=" + resourceDirs);
|
pw.println(prefix + "resourceDirs=" + resourceDirs);
|
||||||
|
}
|
||||||
pw.println(prefix + "dataDir=" + dataDir);
|
pw.println(prefix + "dataDir=" + dataDir);
|
||||||
if (sharedLibraryFiles != null) {
|
if (sharedLibraryFiles != null) {
|
||||||
pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles);
|
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
|
modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||||
if (modeFlags == 0) {
|
if (modeFlags == 0) {
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
|
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
|
||||||
"Requested grant " + targetPkg + " permission to " + uri);
|
"Checking grant " + targetPkg + " permission to " + uri);
|
||||||
|
|
||||||
final IPackageManager pm = AppGlobals.getPackageManager();
|
final IPackageManager pm = AppGlobals.getPackageManager();
|
||||||
|
|
||||||
@ -4113,7 +4120,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
|
if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
|
||||||
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
|
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
|
||||||
"Can't grant URI permission for non-content URI: " + uri);
|
"Can't grant URI permission for non-content URI: " + uri);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = uri.getAuthority();
|
String name = uri.getAuthority();
|
||||||
@ -4130,7 +4137,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
}
|
}
|
||||||
if (pi == null) {
|
if (pi == null) {
|
||||||
Slog.w(TAG, "No content provider found for: " + name);
|
Slog.w(TAG, "No content provider found for: " + name);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int targetUid;
|
int targetUid;
|
||||||
@ -4139,10 +4146,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
if (targetUid < 0) {
|
if (targetUid < 0) {
|
||||||
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
|
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
|
||||||
"Can't grant URI permission no uid for: " + targetPkg);
|
"Can't grant URI permission no uid for: " + targetPkg);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
} catch (RemoteException ex) {
|
} catch (RemoteException ex) {
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First... does the target actually need this permission?
|
// 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.
|
// No need to grant the target this permission.
|
||||||
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
|
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
|
||||||
"Target " + targetPkg + " already has full permission to " + uri);
|
"Target " + targetPkg + " already has full permission to " + uri);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second... is the provider allowing granting of URI permissions?
|
// 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
|
// to the uri, and the target doesn't. Let's now give this to
|
||||||
// the target.
|
// the target.
|
||||||
|
|
||||||
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
|
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
|
||||||
"Granting " + targetPkg + " permission to " + uri);
|
"Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
|
||||||
|
|
||||||
HashMap<Uri, UriPermission> targetUris
|
HashMap<Uri, UriPermission> targetUris
|
||||||
= mGrantedUriPermissions.get(targetUid);
|
= mGrantedUriPermissions.get(targetUid);
|
||||||
@ -4208,39 +4226,65 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
perm.modeFlags |= modeFlags;
|
perm.modeFlags |= modeFlags;
|
||||||
if (activity == null) {
|
if (owner == null) {
|
||||||
perm.globalModeFlags |= modeFlags;
|
perm.globalModeFlags |= modeFlags;
|
||||||
} else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
|
} else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
|
||||||
perm.readActivities.add(activity);
|
perm.readOwners.add(owner);
|
||||||
if (activity.readUriPermissions == null) {
|
owner.addReadPermission(perm);
|
||||||
activity.readUriPermissions = new HashSet<UriPermission>();
|
|
||||||
}
|
|
||||||
activity.readUriPermissions.add(perm);
|
|
||||||
} else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
|
} else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
|
||||||
perm.writeActivities.add(activity);
|
perm.writeOwners.add(owner);
|
||||||
if (activity.writeUriPermissions == null) {
|
owner.addWritePermission(perm);
|
||||||
activity.writeUriPermissions = new HashSet<UriPermission>();
|
|
||||||
}
|
|
||||||
activity.writeUriPermissions.add(perm);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void grantUriPermissionFromIntentLocked(int callingUid,
|
void grantUriPermissionLocked(int callingUid,
|
||||||
String targetPkg, Intent intent, ActivityRecord activity) {
|
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,
|
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"
|
+ " from " + intent + "; flags=0x"
|
||||||
+ Integer.toHexString(intent != null ? intent.getFlags() : 0));
|
+ Integer.toHexString(intent != null ? intent.getFlags() : 0));
|
||||||
|
|
||||||
if (intent == null) {
|
if (intent == null) {
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
Uri data = intent.getData();
|
Uri data = intent.getData();
|
||||||
if (data == null) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
grantUriPermissionLocked(callingUid, targetPkg, data,
|
|
||||||
intent.getFlags(), activity);
|
grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void grantUriPermission(IApplicationThread caller, String targetPkg,
|
public void grantUriPermission(IApplicationThread caller, String targetPkg,
|
||||||
@ -8211,18 +8255,23 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
while (r.pendingStarts.size() > 0) {
|
||||||
while (i < N) {
|
|
||||||
try {
|
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: "
|
if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
|
||||||
+ r.name + " " + r.intent + " args=" + si.intent);
|
+ 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
|
// If somehow we got a dummy start at the front, then
|
||||||
// just drop it here.
|
// just drop it here.
|
||||||
i++;
|
|
||||||
continue;
|
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);
|
bumpServiceExecutingLocked(r);
|
||||||
if (!oomAdjusted) {
|
if (!oomAdjusted) {
|
||||||
oomAdjusted = true;
|
oomAdjusted = true;
|
||||||
@ -8236,10 +8285,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
flags |= Service.START_FLAG_REDELIVERY;
|
flags |= Service.START_FLAG_REDELIVERY;
|
||||||
}
|
}
|
||||||
r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
|
r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
|
||||||
si.deliveredTime = SystemClock.uptimeMillis();
|
|
||||||
r.deliveredStarts.add(si);
|
|
||||||
si.deliveryCount++;
|
|
||||||
i++;
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Remote process gone... we'll let the normal cleanup take
|
// Remote process gone... we'll let the normal cleanup take
|
||||||
// care of this.
|
// care of this.
|
||||||
@ -8249,14 +8294,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i == N) {
|
|
||||||
r.pendingStarts.clear();
|
|
||||||
} else {
|
|
||||||
while (i > 0) {
|
|
||||||
i--;
|
|
||||||
r.pendingStarts.remove(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final boolean requestServiceBindingLocked(ServiceRecord r,
|
private final boolean requestServiceBindingLocked(ServiceRecord r,
|
||||||
@ -8339,7 +8376,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
if (r.lastStartId < 1) {
|
if (r.lastStartId < 1) {
|
||||||
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);
|
sendServiceArgsLocked(r, true);
|
||||||
@ -8359,6 +8396,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
if (N > 0) {
|
if (N > 0) {
|
||||||
for (int i=N-1; i>=0; i--) {
|
for (int i=N-1; i>=0; i--) {
|
||||||
ServiceRecord.StartItem si = r.deliveredStarts.get(i);
|
ServiceRecord.StartItem si = r.deliveredStarts.get(i);
|
||||||
|
si.removeUriPermissionsLocked();
|
||||||
if (si.intent == null) {
|
if (si.intent == null) {
|
||||||
// We'll generate this again if needed.
|
// We'll generate this again if needed.
|
||||||
} else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
|
} else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
|
||||||
@ -8598,7 +8636,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
r.foregroundNoti = null;
|
r.foregroundNoti = null;
|
||||||
|
|
||||||
// Clear start entries.
|
// Clear start entries.
|
||||||
r.deliveredStarts.clear();
|
r.clearDeliveredStartsLocked();
|
||||||
r.pendingStarts.clear();
|
r.pendingStarts.clear();
|
||||||
|
|
||||||
if (r.app != null) {
|
if (r.app != null) {
|
||||||
@ -8658,6 +8696,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
? res.permission : "private to package");
|
? res.permission : "private to package");
|
||||||
}
|
}
|
||||||
ServiceRecord r = res.record;
|
ServiceRecord r = res.record;
|
||||||
|
int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
|
||||||
|
callingUid, r.packageName, service);
|
||||||
if (unscheduleServiceRestartLocked(r)) {
|
if (unscheduleServiceRestartLocked(r)) {
|
||||||
if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
|
if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
|
||||||
+ r.shortName);
|
+ r.shortName);
|
||||||
@ -8668,7 +8708,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
if (r.lastStartId < 1) {
|
if (r.lastStartId < 1) {
|
||||||
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();
|
r.lastActivity = SystemClock.uptimeMillis();
|
||||||
synchronized (r.stats.getBatteryStats()) {
|
synchronized (r.stats.getBatteryStats()) {
|
||||||
r.stats.startRunningLocked();
|
r.stats.startRunningLocked();
|
||||||
@ -8793,7 +8834,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
|
ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
|
||||||
if (si != null) {
|
if (si != null) {
|
||||||
while (r.deliveredStarts.size() > 0) {
|
while (r.deliveredStarts.size() > 0) {
|
||||||
if (r.deliveredStarts.remove(0) == si) {
|
ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
|
||||||
|
cur.removeUriPermissionsLocked();
|
||||||
|
if (cur == si) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import android.graphics.Bitmap;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.EventLog;
|
import android.util.EventLog;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -43,7 +44,7 @@ import java.util.HashSet;
|
|||||||
/**
|
/**
|
||||||
* An entry in the history stack, representing an activity.
|
* 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 ActivityManagerService service; // owner
|
||||||
final ActivityStack stack; // owner
|
final ActivityStack stack; // owner
|
||||||
final ActivityInfo info; // all about me
|
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()
|
* Deliver a new Intent to an existing activity, so that its onNewIntent()
|
||||||
* method will be called at the proper time.
|
* method will be called at the proper time.
|
||||||
*/
|
*/
|
||||||
final void deliverNewIntentLocked(Intent intent) {
|
final void deliverNewIntentLocked(int callingUid, Intent intent) {
|
||||||
boolean sent = false;
|
boolean sent = false;
|
||||||
if (state == ActivityState.RESUMED
|
if (state == ActivityState.RESUMED
|
||||||
&& app != null && app.thread != null) {
|
&& app != null && app.thread != null) {
|
||||||
try {
|
try {
|
||||||
ArrayList<Intent> ar = new ArrayList<Intent>();
|
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);
|
app.thread.scheduleNewIntent(ar, this);
|
||||||
sent = true;
|
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,
|
Slog.w(ActivityManagerService.TAG,
|
||||||
"Exception thrown sending new intent to " + this, e);
|
"Exception thrown sending new intent to " + this, e);
|
||||||
}
|
}
|
||||||
@ -362,23 +369,25 @@ class ActivityRecord extends IApplicationToken.Stub {
|
|||||||
void removeUriPermissionsLocked() {
|
void removeUriPermissionsLocked() {
|
||||||
if (readUriPermissions != null) {
|
if (readUriPermissions != null) {
|
||||||
for (UriPermission perm : readUriPermissions) {
|
for (UriPermission perm : readUriPermissions) {
|
||||||
perm.readActivities.remove(this);
|
perm.readOwners.remove(this);
|
||||||
if (perm.readActivities.size() == 0 && (perm.globalModeFlags
|
if (perm.readOwners.size() == 0 && (perm.globalModeFlags
|
||||||
&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
|
&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
|
||||||
perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
||||||
service.removeUriPermissionIfNeededLocked(perm);
|
service.removeUriPermissionIfNeededLocked(perm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
readUriPermissions = null;
|
||||||
}
|
}
|
||||||
if (writeUriPermissions != null) {
|
if (writeUriPermissions != null) {
|
||||||
for (UriPermission perm : writeUriPermissions) {
|
for (UriPermission perm : writeUriPermissions) {
|
||||||
perm.writeActivities.remove(this);
|
perm.writeOwners.remove(this);
|
||||||
if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
|
if (perm.writeOwners.size() == 0 && (perm.globalModeFlags
|
||||||
&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
|
&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
|
||||||
perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
||||||
service.removeUriPermissionIfNeededLocked(perm);
|
service.removeUriPermissionIfNeededLocked(perm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
writeUriPermissions = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,6 +578,37 @@ class ActivityRecord extends IApplicationToken.Stub {
|
|||||||
state == ActivityState.RESUMED;
|
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() {
|
public String toString() {
|
||||||
if (stringName != null) {
|
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) {
|
if (sourceRecord == null) {
|
||||||
// This activity is not being started from another... in this
|
// This activity is not being started from another... in this
|
||||||
// case we -always- start a new task.
|
// case we -always- start a new task.
|
||||||
@ -2150,7 +2140,7 @@ public class ActivityStack {
|
|||||||
top.task.setIntent(r.intent, r.info);
|
top.task.setIntent(r.intent, r.info);
|
||||||
}
|
}
|
||||||
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
|
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
|
||||||
top.deliverNewIntentLocked(r.intent);
|
top.deliverNewIntentLocked(callingUid, r.intent);
|
||||||
} else {
|
} else {
|
||||||
// A special case: we need to
|
// A special case: we need to
|
||||||
// start the activity because it is not currently
|
// start the activity because it is not currently
|
||||||
@ -2175,7 +2165,7 @@ public class ActivityStack {
|
|||||||
if (taskTop.frontOfTask) {
|
if (taskTop.frontOfTask) {
|
||||||
taskTop.task.setIntent(r.intent, r.info);
|
taskTop.task.setIntent(r.intent, r.info);
|
||||||
}
|
}
|
||||||
taskTop.deliverNewIntentLocked(r.intent);
|
taskTop.deliverNewIntentLocked(callingUid, r.intent);
|
||||||
} else if (!r.intent.filterEquals(taskTop.task.intent)) {
|
} else if (!r.intent.filterEquals(taskTop.task.intent)) {
|
||||||
// In this case we are launching the root activity
|
// In this case we are launching the root activity
|
||||||
// of the task, but with a different intent. We
|
// of the task, but with a different intent. We
|
||||||
@ -2243,7 +2233,7 @@ public class ActivityStack {
|
|||||||
// is the case, so this is it!
|
// is the case, so this is it!
|
||||||
return START_RETURN_INTENT_TO_CALLER;
|
return START_RETURN_INTENT_TO_CALLER;
|
||||||
}
|
}
|
||||||
top.deliverNewIntentLocked(r.intent);
|
top.deliverNewIntentLocked(callingUid, r.intent);
|
||||||
return START_DELIVERED_TO_TOP;
|
return START_DELIVERED_TO_TOP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2288,7 +2278,7 @@ public class ActivityStack {
|
|||||||
sourceRecord.task.taskId, r, launchFlags, true);
|
sourceRecord.task.taskId, r, launchFlags, true);
|
||||||
if (top != null) {
|
if (top != null) {
|
||||||
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
|
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
|
||||||
top.deliverNewIntentLocked(r.intent);
|
top.deliverNewIntentLocked(callingUid, r.intent);
|
||||||
// For paranoia, make sure we have correctly
|
// For paranoia, make sure we have correctly
|
||||||
// resumed the top activity.
|
// resumed the top activity.
|
||||||
if (doResume) {
|
if (doResume) {
|
||||||
@ -2305,7 +2295,7 @@ public class ActivityStack {
|
|||||||
if (where >= 0) {
|
if (where >= 0) {
|
||||||
ActivityRecord top = moveActivityToFrontLocked(where);
|
ActivityRecord top = moveActivityToFrontLocked(where);
|
||||||
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
|
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
|
||||||
top.deliverNewIntentLocked(r.intent);
|
top.deliverNewIntentLocked(callingUid, r.intent);
|
||||||
if (doResume) {
|
if (doResume) {
|
||||||
resumeTopActivityLocked(null);
|
resumeTopActivityLocked(null);
|
||||||
}
|
}
|
||||||
@ -2333,6 +2323,17 @@ public class ActivityStack {
|
|||||||
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
|
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
|
||||||
+ " in new guessed " + r.task);
|
+ " 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) {
|
if (newTask) {
|
||||||
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
|
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import android.os.Bundle;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.PrintWriterPrinter;
|
import android.util.PrintWriterPrinter;
|
||||||
|
import android.util.TimeUtils;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -73,61 +74,65 @@ class BroadcastRecord extends Binder {
|
|||||||
ActivityInfo curReceiver; // info about the receiver that is currently running.
|
ActivityInfo curReceiver; // info about the receiver that is currently running.
|
||||||
|
|
||||||
void dump(PrintWriter pw, String prefix) {
|
void dump(PrintWriter pw, String prefix) {
|
||||||
pw.println(prefix + this);
|
final long now = SystemClock.uptimeMillis();
|
||||||
pw.println(prefix + intent);
|
|
||||||
|
pw.print(prefix); pw.println(this);
|
||||||
|
pw.print(prefix); pw.println(intent);
|
||||||
if (sticky) {
|
if (sticky) {
|
||||||
Bundle bundle = intent.getExtras();
|
Bundle bundle = intent.getExtras();
|
||||||
if (bundle != null) {
|
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.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.println(" ");
|
||||||
pw.println(prefix + "caller=" + callerPackage
|
pw.println(callerApp != null ? callerApp.toShortString() : "null");
|
||||||
+ " callingPid=" + callingPid
|
pw.print(" pid="); pw.print(callingPid);
|
||||||
+ " callingUid=" + callingUid);
|
pw.print(" uid="); pw.println(callingUid);
|
||||||
if (requiredPermission != null) {
|
if (requiredPermission != null) {
|
||||||
pw.println(prefix + "requiredPermission=" + requiredPermission);
|
pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission);
|
||||||
}
|
}
|
||||||
pw.println(prefix + "dispatchTime=" + dispatchTime + " ("
|
pw.print(prefix); pw.print("dispatchTime=");
|
||||||
+ (SystemClock.uptimeMillis()-dispatchTime) + "ms since now)");
|
TimeUtils.formatDuration(dispatchTime, now, pw);
|
||||||
if (finishTime != 0) {
|
if (finishTime != 0) {
|
||||||
pw.println(prefix + "finishTime=" + finishTime + " ("
|
pw.print(" finishTime="); TimeUtils.formatDuration(finishTime, now, pw);
|
||||||
+ (SystemClock.uptimeMillis()-finishTime) + "ms since now)");
|
|
||||||
} else {
|
} else {
|
||||||
pw.println(prefix + "receiverTime=" + receiverTime + " ("
|
pw.print(" receiverTime="); TimeUtils.formatDuration(receiverTime, now, pw);
|
||||||
+ (SystemClock.uptimeMillis()-receiverTime) + "ms since now)");
|
|
||||||
}
|
}
|
||||||
|
pw.println("");
|
||||||
if (anrCount != 0) {
|
if (anrCount != 0) {
|
||||||
pw.println(prefix + "anrCount=" + anrCount);
|
pw.print(prefix); pw.print("anrCount="); pw.println(anrCount);
|
||||||
}
|
}
|
||||||
if (resultTo != null || resultCode != -1 || resultData != null) {
|
if (resultTo != null || resultCode != -1 || resultData != null) {
|
||||||
pw.println(prefix + "resultTo=" + resultTo
|
pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
|
||||||
+ " resultCode=" + resultCode + " resultData=" + resultData);
|
pw.print(" resultCode="); pw.print(resultCode);
|
||||||
|
pw.print(" resultData="); pw.println(resultData);
|
||||||
}
|
}
|
||||||
if (resultExtras != null) {
|
if (resultExtras != null) {
|
||||||
pw.println(prefix + "resultExtras=" + resultExtras);
|
pw.print(prefix); pw.print("resultExtras="); pw.println(resultExtras);
|
||||||
}
|
}
|
||||||
if (resultAbort || ordered || sticky || initialSticky) {
|
if (resultAbort || ordered || sticky || initialSticky) {
|
||||||
pw.println(prefix + "resultAbort=" + resultAbort
|
pw.print(prefix); pw.print("resultAbort="); pw.print(resultAbort);
|
||||||
+ " ordered=" + ordered + " sticky=" + sticky
|
pw.print(" ordered="); pw.print(ordered);
|
||||||
+ " initialSticky=" + initialSticky);
|
pw.print(" sticky="); pw.print(sticky);
|
||||||
|
pw.print(" initialSticky="); pw.println(initialSticky);
|
||||||
}
|
}
|
||||||
if (nextReceiver != 0 || receiver != null) {
|
if (nextReceiver != 0 || receiver != null) {
|
||||||
pw.println(prefix + "nextReceiver=" + nextReceiver
|
pw.print(prefix); pw.print("nextReceiver="); pw.print(nextReceiver);
|
||||||
+ " receiver=" + receiver);
|
pw.print(" receiver="); pw.println(receiver);
|
||||||
}
|
}
|
||||||
if (curFilter != null) {
|
if (curFilter != null) {
|
||||||
pw.println(prefix + "curFilter=" + curFilter);
|
pw.print(prefix); pw.print("curFilter="); pw.println(curFilter);
|
||||||
}
|
}
|
||||||
if (curReceiver != null) {
|
if (curReceiver != null) {
|
||||||
pw.println(prefix + "curReceiver=" + curReceiver);
|
pw.print(prefix); pw.print("curReceiver="); pw.println(curReceiver);
|
||||||
}
|
}
|
||||||
if (curApp != null) {
|
if (curApp != null) {
|
||||||
pw.println(prefix + "curApp=" + curApp);
|
pw.print(prefix); pw.print("curApp="); pw.println(curApp);
|
||||||
pw.println(prefix + "curComponent="
|
pw.print(prefix); pw.print("curComponent=");
|
||||||
+ (curComponent != null ? curComponent.toShortString() : "--"));
|
pw.println((curComponent != null ? curComponent.toShortString() : "--"));
|
||||||
if (curReceiver != null && curReceiver.applicationInfo != null) {
|
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 = " (?)";
|
String stateStr = " (?)";
|
||||||
@ -137,13 +142,14 @@ class BroadcastRecord extends Binder {
|
|||||||
case CALL_IN_RECEIVE: stateStr=" (CALL_IN_RECEIVE)"; break;
|
case CALL_IN_RECEIVE: stateStr=" (CALL_IN_RECEIVE)"; break;
|
||||||
case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_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;
|
final int N = receivers != null ? receivers.size() : 0;
|
||||||
String p2 = prefix + " ";
|
String p2 = prefix + " ";
|
||||||
PrintWriterPrinter printer = new PrintWriterPrinter(pw);
|
PrintWriterPrinter printer = new PrintWriterPrinter(pw);
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
Object o = receivers.get(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)
|
if (o instanceof BroadcastFilter)
|
||||||
((BroadcastFilter)o).dumpBrief(pw, p2);
|
((BroadcastFilter)o).dumpBrief(pw, p2);
|
||||||
else if (o instanceof ResolveInfo)
|
else if (o instanceof ResolveInfo)
|
||||||
|
@ -36,6 +36,7 @@ import android.util.TimeUtils;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -43,6 +44,12 @@ import java.util.List;
|
|||||||
* A running application service.
|
* A running application service.
|
||||||
*/
|
*/
|
||||||
class ServiceRecord extends Binder {
|
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 ActivityManagerService ams;
|
||||||
final BatteryStatsImpl.Uid.Pkg.Serv stats;
|
final BatteryStatsImpl.Uid.Pkg.Serv stats;
|
||||||
final ComponentName name; // service component.
|
final ComponentName name; // service component.
|
||||||
@ -69,29 +76,6 @@ class ServiceRecord extends Binder {
|
|||||||
= new HashMap<IBinder, ConnectionRecord>();
|
= new HashMap<IBinder, ConnectionRecord>();
|
||||||
// IBinder -> ConnectionRecord of all bound clients
|
// 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.
|
ProcessRecord app; // where this service is running or null.
|
||||||
boolean isForeground; // is service currently in foreground mode?
|
boolean isForeground; // is service currently in foreground mode?
|
||||||
int foregroundId; // Notification ID of last foreground req.
|
int foregroundId; // Notification ID of last foreground req.
|
||||||
@ -112,6 +96,104 @@ class ServiceRecord extends Binder {
|
|||||||
|
|
||||||
String stringName; // caching of toString
|
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) {
|
void dumpStartList(PrintWriter pw, String prefix, List<StartItem> list, long now) {
|
||||||
final int N = list.size();
|
final int N = list.size();
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
@ -128,9 +210,22 @@ class ServiceRecord extends Binder {
|
|||||||
if (si.doneExecutingCount != 0) {
|
if (si.doneExecutingCount != 0) {
|
||||||
pw.print(" dxc="); pw.print(si.doneExecutingCount);
|
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());
|
if (si.intent != null) pw.println(si.intent.toString());
|
||||||
else pw.println("null");
|
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() {
|
public String toString() {
|
||||||
if (stringName != null) {
|
if (stringName != null) {
|
||||||
return stringName;
|
return stringName;
|
||||||
|
@ -22,13 +22,20 @@ import android.net.Uri;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
interface UriPermissionOwner {
|
||||||
|
void addReadPermission(UriPermission perm);
|
||||||
|
void addWritePermission(UriPermission perm);
|
||||||
|
void removeReadPermission(UriPermission perm);
|
||||||
|
void removeWritePermission(UriPermission perm);
|
||||||
|
}
|
||||||
|
|
||||||
class UriPermission {
|
class UriPermission {
|
||||||
final int uid;
|
final int uid;
|
||||||
final Uri uri;
|
final Uri uri;
|
||||||
int modeFlags = 0;
|
int modeFlags = 0;
|
||||||
int globalModeFlags = 0;
|
int globalModeFlags = 0;
|
||||||
final HashSet<ActivityRecord> readActivities = new HashSet<ActivityRecord>();
|
final HashSet<UriPermissionOwner> readOwners = new HashSet<UriPermissionOwner>();
|
||||||
final HashSet<ActivityRecord> writeActivities = new HashSet<ActivityRecord>();
|
final HashSet<UriPermissionOwner> writeOwners = new HashSet<UriPermissionOwner>();
|
||||||
|
|
||||||
String stringName;
|
String stringName;
|
||||||
|
|
||||||
@ -41,27 +48,21 @@ class UriPermission {
|
|||||||
if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
|
if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
|
||||||
globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
||||||
modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
||||||
if (readActivities.size() > 0) {
|
if (readOwners.size() > 0) {
|
||||||
for (ActivityRecord r : readActivities) {
|
for (UriPermissionOwner r : readOwners) {
|
||||||
r.readUriPermissions.remove(this);
|
r.removeReadPermission(this);
|
||||||
if (r.readUriPermissions.size() == 0) {
|
|
||||||
r.readUriPermissions = null;
|
|
||||||
}
|
}
|
||||||
}
|
readOwners.clear();
|
||||||
readActivities.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
|
if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
|
||||||
globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
||||||
modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
||||||
if (readActivities.size() > 0) {
|
if (readOwners.size() > 0) {
|
||||||
for (ActivityRecord r : readActivities) {
|
for (UriPermissionOwner r : writeOwners) {
|
||||||
r.writeUriPermissions.remove(this);
|
r.removeWritePermission(this);
|
||||||
if (r.writeUriPermissions.size() == 0) {
|
|
||||||
r.writeUriPermissions = null;
|
|
||||||
}
|
}
|
||||||
}
|
readOwners.clear();
|
||||||
readActivities.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,11 +86,17 @@ class UriPermission {
|
|||||||
pw.print(" uid="); pw.print(uid);
|
pw.print(" uid="); pw.print(uid);
|
||||||
pw.print(" globalModeFlags=0x");
|
pw.print(" globalModeFlags=0x");
|
||||||
pw.println(Integer.toHexString(globalModeFlags));
|
pw.println(Integer.toHexString(globalModeFlags));
|
||||||
if (readActivities.size() != 0) {
|
if (readOwners.size() != 0) {
|
||||||
pw.print(prefix); pw.print("readActivities="); pw.println(readActivities);
|
pw.print(prefix); pw.println("readOwners:");
|
||||||
|
for (UriPermissionOwner owner : readOwners) {
|
||||||
|
pw.print(prefix); pw.print(" * "); pw.println(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (writeOwners.size() != 0) {
|
||||||
|
pw.print(prefix); pw.println("writeOwners:");
|
||||||
|
for (UriPermissionOwner owner : writeOwners) {
|
||||||
|
pw.print(prefix); pw.print(" * "); pw.println(owner);
|
||||||
}
|
}
|
||||||
if (writeActivities.size() != 0) {
|
|
||||||
pw.print(prefix); pw.print("writeActivities="); pw.println(writeActivities);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user