Implement issue #36590595: Add ability to associated a ClipData with JobInfo
Yum! Also needed to have a Context.revokeUriPermission() variant that is sane, so reasonable CTS tests can be written. Test: new ClipDataJobTest added. Change-Id: Ia3135ea788a6e32c971bae7dab3a844d0ef4139c
This commit is contained in:
@@ -6740,6 +6740,8 @@ package android.app.job {
|
||||
public class JobInfo implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getBackoffPolicy();
|
||||
method public android.content.ClipData getClipData();
|
||||
method public int getClipGrantFlags();
|
||||
method public android.os.PersistableBundle getExtras();
|
||||
method public long getFlexMillis();
|
||||
method public int getId();
|
||||
@@ -6778,6 +6780,7 @@ package android.app.job {
|
||||
method public android.app.job.JobInfo.Builder addTriggerContentUri(android.app.job.JobInfo.TriggerContentUri);
|
||||
method public android.app.job.JobInfo build();
|
||||
method public android.app.job.JobInfo.Builder setBackoffCriteria(long, int);
|
||||
method public android.app.job.JobInfo.Builder setClipData(android.content.ClipData, int);
|
||||
method public android.app.job.JobInfo.Builder setExtras(android.os.PersistableBundle);
|
||||
method public android.app.job.JobInfo.Builder setMinimumLatency(long);
|
||||
method public android.app.job.JobInfo.Builder setOverrideDeadline(long);
|
||||
@@ -6806,6 +6809,8 @@ package android.app.job {
|
||||
|
||||
public class JobParameters implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.content.ClipData getClipData();
|
||||
method public int getClipGrantFlags();
|
||||
method public android.os.PersistableBundle getExtras();
|
||||
method public int getJobId();
|
||||
method public android.os.Bundle getTransientExtras();
|
||||
@@ -8841,6 +8846,7 @@ package android.content {
|
||||
method public abstract deprecated void removeStickyBroadcast(android.content.Intent);
|
||||
method public abstract deprecated void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
method public abstract void revokeUriPermission(android.net.Uri, int);
|
||||
method public abstract void revokeUriPermission(java.lang.String, android.net.Uri, int);
|
||||
method public abstract void sendBroadcast(android.content.Intent);
|
||||
method public abstract void sendBroadcast(android.content.Intent, java.lang.String);
|
||||
method public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
@@ -9033,6 +9039,7 @@ package android.content {
|
||||
method public deprecated void removeStickyBroadcast(android.content.Intent);
|
||||
method public deprecated void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
method public void revokeUriPermission(android.net.Uri, int);
|
||||
method public void revokeUriPermission(java.lang.String, android.net.Uri, int);
|
||||
method public void sendBroadcast(android.content.Intent);
|
||||
method public void sendBroadcast(android.content.Intent, java.lang.String);
|
||||
method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
@@ -40664,6 +40671,7 @@ package android.test.mock {
|
||||
method public void removeStickyBroadcast(android.content.Intent);
|
||||
method public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
method public void revokeUriPermission(android.net.Uri, int);
|
||||
method public void revokeUriPermission(java.lang.String, android.net.Uri, int);
|
||||
method public void sendBroadcast(android.content.Intent);
|
||||
method public void sendBroadcast(android.content.Intent, java.lang.String);
|
||||
method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
|
||||
@@ -7167,6 +7167,8 @@ package android.app.job {
|
||||
public class JobInfo implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getBackoffPolicy();
|
||||
method public android.content.ClipData getClipData();
|
||||
method public int getClipGrantFlags();
|
||||
method public android.os.PersistableBundle getExtras();
|
||||
method public long getFlexMillis();
|
||||
method public int getId();
|
||||
@@ -7205,6 +7207,7 @@ package android.app.job {
|
||||
method public android.app.job.JobInfo.Builder addTriggerContentUri(android.app.job.JobInfo.TriggerContentUri);
|
||||
method public android.app.job.JobInfo build();
|
||||
method public android.app.job.JobInfo.Builder setBackoffCriteria(long, int);
|
||||
method public android.app.job.JobInfo.Builder setClipData(android.content.ClipData, int);
|
||||
method public android.app.job.JobInfo.Builder setExtras(android.os.PersistableBundle);
|
||||
method public android.app.job.JobInfo.Builder setMinimumLatency(long);
|
||||
method public android.app.job.JobInfo.Builder setOverrideDeadline(long);
|
||||
@@ -7233,6 +7236,8 @@ package android.app.job {
|
||||
|
||||
public class JobParameters implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.content.ClipData getClipData();
|
||||
method public int getClipGrantFlags();
|
||||
method public android.os.PersistableBundle getExtras();
|
||||
method public int getJobId();
|
||||
method public android.os.Bundle getTransientExtras();
|
||||
@@ -9333,6 +9338,7 @@ package android.content {
|
||||
method public abstract deprecated void removeStickyBroadcast(android.content.Intent);
|
||||
method public abstract deprecated void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
method public abstract void revokeUriPermission(android.net.Uri, int);
|
||||
method public abstract void revokeUriPermission(java.lang.String, android.net.Uri, int);
|
||||
method public abstract void sendBroadcast(android.content.Intent);
|
||||
method public abstract void sendBroadcast(android.content.Intent, java.lang.String);
|
||||
method public abstract void sendBroadcast(android.content.Intent, java.lang.String, android.os.Bundle);
|
||||
@@ -9539,6 +9545,7 @@ package android.content {
|
||||
method public deprecated void removeStickyBroadcast(android.content.Intent);
|
||||
method public deprecated void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
method public void revokeUriPermission(android.net.Uri, int);
|
||||
method public void revokeUriPermission(java.lang.String, android.net.Uri, int);
|
||||
method public void sendBroadcast(android.content.Intent);
|
||||
method public void sendBroadcast(android.content.Intent, java.lang.String);
|
||||
method public void sendBroadcast(android.content.Intent, java.lang.String, android.os.Bundle);
|
||||
@@ -44099,6 +44106,7 @@ package android.test.mock {
|
||||
method public void removeStickyBroadcast(android.content.Intent);
|
||||
method public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
method public void revokeUriPermission(android.net.Uri, int);
|
||||
method public void revokeUriPermission(java.lang.String, android.net.Uri, int);
|
||||
method public void sendBroadcast(android.content.Intent);
|
||||
method public void sendBroadcast(android.content.Intent, java.lang.String);
|
||||
method public void sendBroadcast(android.content.Intent, java.lang.String, android.os.Bundle);
|
||||
|
||||
@@ -6769,6 +6769,8 @@ package android.app.job {
|
||||
public class JobInfo implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getBackoffPolicy();
|
||||
method public android.content.ClipData getClipData();
|
||||
method public int getClipGrantFlags();
|
||||
method public android.os.PersistableBundle getExtras();
|
||||
method public long getFlexMillis();
|
||||
method public int getId();
|
||||
@@ -6807,6 +6809,7 @@ package android.app.job {
|
||||
method public android.app.job.JobInfo.Builder addTriggerContentUri(android.app.job.JobInfo.TriggerContentUri);
|
||||
method public android.app.job.JobInfo build();
|
||||
method public android.app.job.JobInfo.Builder setBackoffCriteria(long, int);
|
||||
method public android.app.job.JobInfo.Builder setClipData(android.content.ClipData, int);
|
||||
method public android.app.job.JobInfo.Builder setExtras(android.os.PersistableBundle);
|
||||
method public android.app.job.JobInfo.Builder setMinimumLatency(long);
|
||||
method public android.app.job.JobInfo.Builder setOverrideDeadline(long);
|
||||
@@ -6835,6 +6838,8 @@ package android.app.job {
|
||||
|
||||
public class JobParameters implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.content.ClipData getClipData();
|
||||
method public int getClipGrantFlags();
|
||||
method public android.os.PersistableBundle getExtras();
|
||||
method public int getJobId();
|
||||
method public android.os.Bundle getTransientExtras();
|
||||
@@ -8873,6 +8878,7 @@ package android.content {
|
||||
method public abstract deprecated void removeStickyBroadcast(android.content.Intent);
|
||||
method public abstract deprecated void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
method public abstract void revokeUriPermission(android.net.Uri, int);
|
||||
method public abstract void revokeUriPermission(java.lang.String, android.net.Uri, int);
|
||||
method public abstract void sendBroadcast(android.content.Intent);
|
||||
method public abstract void sendBroadcast(android.content.Intent, java.lang.String);
|
||||
method public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
@@ -9066,6 +9072,7 @@ package android.content {
|
||||
method public deprecated void removeStickyBroadcast(android.content.Intent);
|
||||
method public deprecated void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
method public void revokeUriPermission(android.net.Uri, int);
|
||||
method public void revokeUriPermission(java.lang.String, android.net.Uri, int);
|
||||
method public void sendBroadcast(android.content.Intent);
|
||||
method public void sendBroadcast(android.content.Intent, java.lang.String);
|
||||
method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
@@ -40868,6 +40875,7 @@ package android.test.mock {
|
||||
method public void removeStickyBroadcast(android.content.Intent);
|
||||
method public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
method public void revokeUriPermission(android.net.Uri, int);
|
||||
method public void revokeUriPermission(java.lang.String, android.net.Uri, int);
|
||||
method public void sendBroadcast(android.content.Intent);
|
||||
method public void sendBroadcast(android.content.Intent, java.lang.String);
|
||||
method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
|
||||
|
||||
@@ -1790,7 +1790,18 @@ class ContextImpl extends Context {
|
||||
public void revokeUriPermission(Uri uri, int modeFlags) {
|
||||
try {
|
||||
ActivityManager.getService().revokeUriPermission(
|
||||
mMainThread.getApplicationThread(),
|
||||
mMainThread.getApplicationThread(), null,
|
||||
ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeUriPermission(String targetPackage, Uri uri, int modeFlags) {
|
||||
try {
|
||||
ActivityManager.getService().revokeUriPermission(
|
||||
mMainThread.getApplicationThread(), targetPackage,
|
||||
ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
|
||||
@@ -172,7 +172,8 @@ interface IActivityManager {
|
||||
in IBinder callerToken);
|
||||
void grantUriPermission(in IApplicationThread caller, in String targetPkg, in Uri uri,
|
||||
int mode, int userId);
|
||||
void revokeUriPermission(in IApplicationThread caller, in Uri uri, int mode, int userId);
|
||||
void revokeUriPermission(in IApplicationThread caller, in String targetPkg, in Uri uri,
|
||||
int mode, int userId);
|
||||
void setActivityController(in IActivityController watcher, boolean imAMonkey);
|
||||
void showWaitingForDebugger(in IApplicationThread who, boolean waiting);
|
||||
/*
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.util.TimeUtils.formatDuration;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ClipData;
|
||||
import android.content.ComponentName;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@@ -197,6 +198,8 @@ public class JobInfo implements Parcelable {
|
||||
private final int jobId;
|
||||
private final PersistableBundle extras;
|
||||
private final Bundle transientExtras;
|
||||
private final ClipData clipData;
|
||||
private final int clipGrantFlags;
|
||||
private final ComponentName service;
|
||||
private final int constraintFlags;
|
||||
private final TriggerContentUri[] triggerContentUris;
|
||||
@@ -239,6 +242,21 @@ public class JobInfo implements Parcelable {
|
||||
return transientExtras;
|
||||
}
|
||||
|
||||
/**
|
||||
* ClipData of information that is returned to your application at execution time,
|
||||
* but not persisted by the system.
|
||||
*/
|
||||
public ClipData getClipData() {
|
||||
return clipData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission grants that go along with {@link #getClipData}.
|
||||
*/
|
||||
public int getClipGrantFlags() {
|
||||
return clipGrantFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of the service endpoint that will be called back into by the JobScheduler.
|
||||
*/
|
||||
@@ -415,6 +433,13 @@ public class JobInfo implements Parcelable {
|
||||
jobId = in.readInt();
|
||||
extras = in.readPersistableBundle();
|
||||
transientExtras = in.readBundle();
|
||||
if (in.readInt() != 0) {
|
||||
clipData = ClipData.CREATOR.createFromParcel(in);
|
||||
clipGrantFlags = in.readInt();
|
||||
} else {
|
||||
clipData = null;
|
||||
clipGrantFlags = 0;
|
||||
}
|
||||
service = in.readParcelable(null);
|
||||
constraintFlags = in.readInt();
|
||||
triggerContentUris = in.createTypedArray(TriggerContentUri.CREATOR);
|
||||
@@ -439,6 +464,8 @@ public class JobInfo implements Parcelable {
|
||||
jobId = b.mJobId;
|
||||
extras = b.mExtras.deepCopy();
|
||||
transientExtras = b.mTransientExtras.deepCopy();
|
||||
clipData = b.mClipData;
|
||||
clipGrantFlags = b.mClipGrantFlags;
|
||||
service = b.mJobService;
|
||||
constraintFlags = b.mConstraintFlags;
|
||||
triggerContentUris = b.mTriggerContentUris != null
|
||||
@@ -471,6 +498,13 @@ public class JobInfo implements Parcelable {
|
||||
out.writeInt(jobId);
|
||||
out.writePersistableBundle(extras);
|
||||
out.writeBundle(transientExtras);
|
||||
if (clipData != null) {
|
||||
out.writeInt(1);
|
||||
clipData.writeToParcel(out, flags);
|
||||
out.writeInt(clipGrantFlags);
|
||||
} else {
|
||||
out.writeInt(0);
|
||||
}
|
||||
out.writeParcelable(service, flags);
|
||||
out.writeInt(constraintFlags);
|
||||
out.writeTypedArray(triggerContentUris, flags);
|
||||
@@ -597,6 +631,8 @@ public class JobInfo implements Parcelable {
|
||||
private final ComponentName mJobService;
|
||||
private PersistableBundle mExtras = PersistableBundle.EMPTY;
|
||||
private Bundle mTransientExtras = Bundle.EMPTY;
|
||||
private ClipData mClipData;
|
||||
private int mClipGrantFlags;
|
||||
private int mPriority = PRIORITY_DEFAULT;
|
||||
private int mFlags;
|
||||
// Requirements.
|
||||
@@ -668,6 +704,34 @@ public class JobInfo implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a {@link ClipData} associated with this Job.
|
||||
*
|
||||
* <p>The main purpose of providing a ClipData is to allow granting of
|
||||
* URI permissions for data associated with the clip. The exact kind
|
||||
* of permission grant to perform is specified through <var>grantFlags</var>.
|
||||
*
|
||||
* <p>If the ClipData contains items that are Intents, any
|
||||
* grant flags in those Intents will be ignored. Only flags provided as an argument
|
||||
* to this method are respected, and will be applied to all Uri or
|
||||
* Intent items in the clip (or sub-items of the clip).
|
||||
*
|
||||
* <p>Because setting this property is not compatible with persisted
|
||||
* jobs, doing so will throw an {@link java.lang.IllegalArgumentException} when
|
||||
* {@link android.app.job.JobInfo.Builder#build()} is called.</p>
|
||||
*
|
||||
* @param clip The new clip to set. May be null to clear the current clip.
|
||||
* @param grantFlags The desired permissions to grant for any URIs. This should be
|
||||
* a combination of {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION},
|
||||
* {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION}, and
|
||||
* {@link android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION}.
|
||||
*/
|
||||
public Builder setClipData(ClipData clip, int grantFlags) {
|
||||
mClipData = clip;
|
||||
mClipGrantFlags = grantFlags;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some description of the kind of network type your job needs to have.
|
||||
* Not calling this function means the network is not necessary, as the default is
|
||||
@@ -892,25 +956,33 @@ public class JobInfo implements Parcelable {
|
||||
"constraints, this is not allowed.");
|
||||
}
|
||||
// Check that a deadline was not set on a periodic job.
|
||||
if (mIsPeriodic && (mMaxExecutionDelayMillis != 0L)) {
|
||||
throw new IllegalArgumentException("Can't call setOverrideDeadline() on a " +
|
||||
"periodic job.");
|
||||
if (mIsPeriodic) {
|
||||
if (mMaxExecutionDelayMillis != 0L) {
|
||||
throw new IllegalArgumentException("Can't call setOverrideDeadline() on a " +
|
||||
"periodic job.");
|
||||
}
|
||||
if (mMinLatencyMillis != 0L) {
|
||||
throw new IllegalArgumentException("Can't call setMinimumLatency() on a " +
|
||||
"periodic job");
|
||||
}
|
||||
if (mTriggerContentUris != null) {
|
||||
throw new IllegalArgumentException("Can't call addTriggerContentUri() on a " +
|
||||
"periodic job");
|
||||
}
|
||||
}
|
||||
if (mIsPeriodic && (mMinLatencyMillis != 0L)) {
|
||||
throw new IllegalArgumentException("Can't call setMinimumLatency() on a " +
|
||||
"periodic job");
|
||||
}
|
||||
if (mIsPeriodic && (mTriggerContentUris != null)) {
|
||||
throw new IllegalArgumentException("Can't call addTriggerContentUri() on a " +
|
||||
"periodic job");
|
||||
}
|
||||
if (mIsPersisted && (mTriggerContentUris != null)) {
|
||||
throw new IllegalArgumentException("Can't call addTriggerContentUri() on a " +
|
||||
"persisted job");
|
||||
}
|
||||
if (mIsPersisted && !mTransientExtras.isEmpty()) {
|
||||
throw new IllegalArgumentException("Can't call setTransientExtras() on a " +
|
||||
"persisted job");
|
||||
if (mIsPersisted) {
|
||||
if (mTriggerContentUris != null) {
|
||||
throw new IllegalArgumentException("Can't call addTriggerContentUri() on a " +
|
||||
"persisted job");
|
||||
}
|
||||
if (!mTransientExtras.isEmpty()) {
|
||||
throw new IllegalArgumentException("Can't call setTransientExtras() on a " +
|
||||
"persisted job");
|
||||
}
|
||||
if (mClipData != null) {
|
||||
throw new IllegalArgumentException("Can't call setClipData() on a " +
|
||||
"persisted job");
|
||||
}
|
||||
}
|
||||
if (mBackoffPolicySet && (mConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
|
||||
throw new IllegalArgumentException("An idle mode job will not respect any" +
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.app.job;
|
||||
|
||||
import android.app.job.IJobCallback;
|
||||
import android.content.ClipData;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
@@ -44,6 +45,8 @@ public class JobParameters implements Parcelable {
|
||||
private final int jobId;
|
||||
private final PersistableBundle extras;
|
||||
private final Bundle transientExtras;
|
||||
private final ClipData clipData;
|
||||
private final int clipGrantFlags;
|
||||
private final IBinder callback;
|
||||
private final boolean overrideDeadlineExpired;
|
||||
private final Uri[] mTriggeredContentUris;
|
||||
@@ -53,11 +56,14 @@ public class JobParameters implements Parcelable {
|
||||
|
||||
/** @hide */
|
||||
public JobParameters(IBinder callback, int jobId, PersistableBundle extras,
|
||||
Bundle transientExtras, boolean overrideDeadlineExpired, Uri[] triggeredContentUris,
|
||||
Bundle transientExtras, ClipData clipData, int clipGrantFlags,
|
||||
boolean overrideDeadlineExpired, Uri[] triggeredContentUris,
|
||||
String[] triggeredContentAuthorities) {
|
||||
this.jobId = jobId;
|
||||
this.extras = extras;
|
||||
this.transientExtras = transientExtras;
|
||||
this.clipData = clipData;
|
||||
this.clipGrantFlags = clipGrantFlags;
|
||||
this.callback = callback;
|
||||
this.overrideDeadlineExpired = overrideDeadlineExpired;
|
||||
this.mTriggeredContentUris = triggeredContentUris;
|
||||
@@ -97,6 +103,24 @@ public class JobParameters implements Parcelable {
|
||||
return transientExtras;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The clip you passed in when constructing this job with
|
||||
* {@link android.app.job.JobInfo.Builder#setClipData(ClipData, int)}. Will be null
|
||||
* if it was not set.
|
||||
*/
|
||||
public ClipData getClipData() {
|
||||
return clipData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The clip grant flags you passed in when constructing this job with
|
||||
* {@link android.app.job.JobInfo.Builder#setClipData(ClipData, int)}. Will be 0
|
||||
* if it was not set.
|
||||
*/
|
||||
public int getClipGrantFlags() {
|
||||
return clipGrantFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* For jobs with {@link android.app.job.JobInfo.Builder#setOverrideDeadline(long)} set, this
|
||||
* provides an easy way to tell whether the job is being executed due to the deadline
|
||||
@@ -140,6 +164,13 @@ public class JobParameters implements Parcelable {
|
||||
jobId = in.readInt();
|
||||
extras = in.readPersistableBundle();
|
||||
transientExtras = in.readBundle();
|
||||
if (in.readInt() != 0) {
|
||||
clipData = ClipData.CREATOR.createFromParcel(in);
|
||||
clipGrantFlags = in.readInt();
|
||||
} else {
|
||||
clipData = null;
|
||||
clipGrantFlags = 0;
|
||||
}
|
||||
callback = in.readStrongBinder();
|
||||
overrideDeadlineExpired = in.readInt() == 1;
|
||||
mTriggeredContentUris = in.createTypedArray(Uri.CREATOR);
|
||||
@@ -162,6 +193,13 @@ public class JobParameters implements Parcelable {
|
||||
dest.writeInt(jobId);
|
||||
dest.writePersistableBundle(extras);
|
||||
dest.writeBundle(transientExtras);
|
||||
if (clipData != null) {
|
||||
dest.writeInt(1);
|
||||
clipData.writeToParcel(dest, flags);
|
||||
dest.writeInt(clipGrantFlags);
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
dest.writeStrongBinder(callback);
|
||||
dest.writeInt(overrideDeadlineExpired ? 1 : 0);
|
||||
dest.writeTypedArray(mTriggeredContentUris, flags);
|
||||
|
||||
@@ -4078,8 +4078,8 @@ public abstract class Context {
|
||||
|
||||
/**
|
||||
* Remove all permissions to access a particular content provider Uri
|
||||
* that were previously added with {@link #grantUriPermission}. The given
|
||||
* Uri will match all previously granted Uris that are the same or a
|
||||
* that were previously added with {@link #grantUriPermission} or <em>any other</em> mechanism.
|
||||
* The given Uri will match all previously granted Uris that are the same or a
|
||||
* sub-path of the given Uri. That is, revoking "content://foo/target" will
|
||||
* revoke both "content://foo/target" and "content://foo/target/sub", but not
|
||||
* "content://foo". It will not remove any prefix grants that exist at a
|
||||
@@ -4089,10 +4089,16 @@ public abstract class Context {
|
||||
* regular permission access to a Uri, but had received access to it through
|
||||
* a specific Uri permission grant, you could not revoke that grant with this
|
||||
* function and a {@link SecurityException} would be thrown. As of
|
||||
* {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this function will not throw a security exception,
|
||||
* but will remove whatever permission grants to the Uri had been given to the app
|
||||
* {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this function will not throw a security
|
||||
* exception, but will remove whatever permission grants to the Uri had been given to the app
|
||||
* (or none).</p>
|
||||
*
|
||||
* <p>Unlike {@link #revokeUriPermission(String, Uri, int)}, this method impacts all permission
|
||||
* grants matching the given Uri, for any package they had been granted to, through any
|
||||
* mechanism this had happened (such as indirectly through the clipboard, activity launch,
|
||||
* service start, etc). That means this can be potentially dangerous to use, as it can
|
||||
* revoke grants that another app could be strongly expecting to stick around.</p>
|
||||
*
|
||||
* @param uri The Uri you would like to revoke access to.
|
||||
* @param modeFlags The desired access modes. Any combination of
|
||||
* {@link Intent#FLAG_GRANT_READ_URI_PERMISSION
|
||||
@@ -4104,6 +4110,34 @@ public abstract class Context {
|
||||
*/
|
||||
public abstract void revokeUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags);
|
||||
|
||||
/**
|
||||
* Remove permissions to access a particular content provider Uri
|
||||
* that were previously added with {@link #grantUriPermission} for a specific target
|
||||
* package. The given Uri will match all previously granted Uris that are the same or a
|
||||
* sub-path of the given Uri. That is, revoking "content://foo/target" will
|
||||
* revoke both "content://foo/target" and "content://foo/target/sub", but not
|
||||
* "content://foo". It will not remove any prefix grants that exist at a
|
||||
* higher level.
|
||||
*
|
||||
* <p>Unlike {@link #revokeUriPermission(Uri, int)}, this method will <em>only</em>
|
||||
* revoke permissions that had been explicitly granted through {@link #grantUriPermission}
|
||||
* and only for the package specified. Any matching grants that have happened through
|
||||
* other mechanisms (clipboard, activity launching, service starting, etc) will not be
|
||||
* removed.</p>
|
||||
*
|
||||
* @param toPackage The package you had previously granted access to.
|
||||
* @param uri The Uri you would like to revoke access to.
|
||||
* @param modeFlags The desired access modes. Any combination of
|
||||
* {@link Intent#FLAG_GRANT_READ_URI_PERMISSION
|
||||
* Intent.FLAG_GRANT_READ_URI_PERMISSION} or
|
||||
* {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
* Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
|
||||
*
|
||||
* @see #grantUriPermission
|
||||
*/
|
||||
public abstract void revokeUriPermission(String toPackage, Uri uri,
|
||||
@Intent.AccessUriMode int modeFlags);
|
||||
|
||||
/**
|
||||
* Determine whether a particular process and user ID has been granted
|
||||
* permission to access a specific URI. This only checks for permissions
|
||||
|
||||
@@ -780,6 +780,11 @@ public class ContextWrapper extends Context {
|
||||
mBase.revokeUriPermission(uri, modeFlags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeUriPermission(String targetPackage, Uri uri, int modeFlags) {
|
||||
mBase.revokeUriPermission(targetPackage, uri, modeFlags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
|
||||
return mBase.checkUriPermission(uri, pid, uid, modeFlags);
|
||||
|
||||
@@ -310,6 +310,20 @@ public class BaseBundle {
|
||||
return mMap.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide this should probably be the implementation of isEmpty(). To do that we
|
||||
* need to ensure we always use the special empty parcel form when the bundle is
|
||||
* empty. (This may already be the case, but to be safe we'll do this later when
|
||||
* we aren't trying to stabilize.)
|
||||
*/
|
||||
public boolean maybeIsEmpty() {
|
||||
if (isParcelled()) {
|
||||
return isEmptyParcel();
|
||||
} else {
|
||||
return isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all elements from the mapping of this Bundle.
|
||||
*/
|
||||
|
||||
@@ -1209,4 +1209,18 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
|
||||
}
|
||||
return "Bundle[" + mMap.toString() + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public synchronized String toShortString() {
|
||||
if (mParcelledData != null) {
|
||||
if (isEmptyParcel()) {
|
||||
return "EMPTY_PARCEL";
|
||||
} else {
|
||||
return "mParcelledData.dataSize=" + mParcelledData.dataSize();
|
||||
}
|
||||
}
|
||||
return mMap.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,4 +309,16 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
|
||||
}
|
||||
return "PersistableBundle[" + mMap.toString() + "]";
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
synchronized public String toShortString() {
|
||||
if (mParcelledData != null) {
|
||||
if (isEmptyParcel()) {
|
||||
return "EMPTY_PARCEL";
|
||||
} else {
|
||||
return "mParcelledData.dataSize=" + mParcelledData.dataSize();
|
||||
}
|
||||
}
|
||||
return mMap.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2386,7 +2386,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
} break;
|
||||
case DELETE_DUMPHEAP_MSG: {
|
||||
revokeUriPermission(ActivityThread.currentActivityThread().getApplicationThread(),
|
||||
DumpHeapActivity.JAVA_URI,
|
||||
null, DumpHeapActivity.JAVA_URI,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
|
||||
UserHandle.myUserId());
|
||||
@@ -8944,7 +8944,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private void revokeUriPermissionLocked(int callingUid, GrantUri grantUri, final int modeFlags) {
|
||||
private void revokeUriPermissionLocked(String targetPackage, int callingUid, GrantUri grantUri,
|
||||
final int modeFlags) {
|
||||
if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
|
||||
"Revoking all granted permissions to " + grantUri);
|
||||
|
||||
@@ -8965,8 +8966,11 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
|
||||
if (perms != null) {
|
||||
boolean persistChanged = false;
|
||||
for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
|
||||
final UriPermission perm = it.next();
|
||||
for (int i = perms.size()-1; i >= 0; i--) {
|
||||
final UriPermission perm = perms.valueAt(i);
|
||||
if (targetPackage != null && !targetPackage.equals(perm.targetPkg)) {
|
||||
continue;
|
||||
}
|
||||
if (perm.uri.sourceUserId == grantUri.sourceUserId
|
||||
&& perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
|
||||
if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
|
||||
@@ -8975,7 +8979,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
persistChanged |= perm.revokeModes(
|
||||
modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
|
||||
if (perm.modeFlags == 0) {
|
||||
it.remove();
|
||||
perms.removeAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8992,29 +8996,30 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
boolean persistChanged = false;
|
||||
|
||||
// Go through all of the permissions and remove any that match.
|
||||
int N = mGrantedUriPermissions.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
for (int i = mGrantedUriPermissions.size()-1; i >= 0; i--) {
|
||||
final int targetUid = mGrantedUriPermissions.keyAt(i);
|
||||
final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
|
||||
|
||||
for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
|
||||
final UriPermission perm = it.next();
|
||||
for (int j = perms.size()-1; j >= 0; j--) {
|
||||
final UriPermission perm = perms.valueAt(j);
|
||||
if (targetPackage != null && !targetPackage.equals(perm.targetPkg)) {
|
||||
continue;
|
||||
}
|
||||
if (perm.uri.sourceUserId == grantUri.sourceUserId
|
||||
&& perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
|
||||
if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
|
||||
"Revoking " + perm.targetUid + " permission to " + perm.uri);
|
||||
persistChanged |= perm.revokeModes(
|
||||
modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
|
||||
modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION,
|
||||
targetPackage == null);
|
||||
if (perm.modeFlags == 0) {
|
||||
it.remove();
|
||||
perms.removeAt(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (perms.isEmpty()) {
|
||||
mGrantedUriPermissions.remove(targetUid);
|
||||
N--;
|
||||
i--;
|
||||
mGrantedUriPermissions.removeAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9028,8 +9033,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
* @param userId The userId in which the uri is to be resolved.
|
||||
*/
|
||||
@Override
|
||||
public void revokeUriPermission(IApplicationThread caller, Uri uri, final int modeFlags,
|
||||
int userId) {
|
||||
public void revokeUriPermission(IApplicationThread caller, String targetPackage, Uri uri,
|
||||
final int modeFlags, int userId) {
|
||||
enforceNotIsolatedCaller("revokeUriPermission");
|
||||
synchronized(this) {
|
||||
final ProcessRecord r = getRecordForAppLocked(caller);
|
||||
@@ -9056,7 +9061,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
return;
|
||||
}
|
||||
|
||||
revokeUriPermissionLocked(r.uid, new GrantUri(userId, uri, false), modeFlags);
|
||||
revokeUriPermissionLocked(targetPackage, r.uid, new GrantUri(userId, uri, false),
|
||||
modeFlags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21164,7 +21170,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
public void run() {
|
||||
revokeUriPermission(ActivityThread.currentActivityThread()
|
||||
.getApplicationThread(),
|
||||
DumpHeapActivity.JAVA_URI,
|
||||
null, DumpHeapActivity.JAVA_URI,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
|
||||
UserHandle.myUserId());
|
||||
|
||||
@@ -616,6 +616,9 @@ public final class JobSchedulerService extends com.android.server.SystemService
|
||||
}
|
||||
}
|
||||
|
||||
// This may throw a SecurityException.
|
||||
jobStatus.prepare(ActivityManager.getService());
|
||||
|
||||
toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
|
||||
if (toCancel != null) {
|
||||
cancelJobImpl(toCancel, jobStatus);
|
||||
@@ -712,6 +715,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
|
||||
|
||||
private void cancelJobImpl(JobStatus cancelled, JobStatus incomingJob) {
|
||||
if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString());
|
||||
cancelled.unprepare(ActivityManager.getService());
|
||||
stopTrackingJob(cancelled, incomingJob, true /* writeBack */);
|
||||
synchronized (mLock) {
|
||||
// Remove from pending queue.
|
||||
@@ -892,6 +896,9 @@ public final class JobSchedulerService extends com.android.server.SystemService
|
||||
*/
|
||||
private void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) {
|
||||
synchronized (mLock) {
|
||||
if (!jobStatus.isPrepared()) {
|
||||
Slog.wtf(TAG, "Not yet prepared when started tracking: " + jobStatus);
|
||||
}
|
||||
final boolean update = mJobs.add(jobStatus);
|
||||
if (mReadyToRock) {
|
||||
for (int i = 0; i < mControllers.size(); i++) {
|
||||
@@ -1078,11 +1085,22 @@ public final class JobSchedulerService extends com.android.server.SystemService
|
||||
// that may cause ordering problems if the app removes jobStatus while in here.
|
||||
if (needsReschedule) {
|
||||
JobStatus rescheduled = getRescheduleJobForFailure(jobStatus);
|
||||
try {
|
||||
rescheduled.prepare(ActivityManager.getService());
|
||||
} catch (SecurityException e) {
|
||||
Slog.w(TAG, "Unable to regrant job permissions for " + rescheduled);
|
||||
}
|
||||
startTrackingJob(rescheduled, jobStatus);
|
||||
} else if (jobStatus.getJob().isPeriodic()) {
|
||||
JobStatus rescheduledPeriodic = getRescheduleJobForPeriodic(jobStatus);
|
||||
try {
|
||||
rescheduledPeriodic.prepare(ActivityManager.getService());
|
||||
} catch (SecurityException e) {
|
||||
Slog.w(TAG, "Unable to regrant job permissions for " + rescheduledPeriodic);
|
||||
}
|
||||
startTrackingJob(rescheduledPeriodic, jobStatus);
|
||||
}
|
||||
jobStatus.unprepare(ActivityManager.getService());
|
||||
reportActive();
|
||||
mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.job;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.job.JobInfo;
|
||||
import android.app.job.JobParameters;
|
||||
import android.app.job.IJobCallback;
|
||||
import android.app.job.IJobService;
|
||||
@@ -187,9 +188,10 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne
|
||||
triggeredAuthorities = new String[job.changedAuthorities.size()];
|
||||
job.changedAuthorities.toArray(triggeredAuthorities);
|
||||
}
|
||||
mParams = new JobParameters(this, job.getJobId(), job.getExtras(),
|
||||
job.getTransientExtras(), isDeadlineExpired,
|
||||
triggeredUris, triggeredAuthorities);
|
||||
final JobInfo ji = job.getJob();
|
||||
mParams = new JobParameters(this, job.getJobId(), ji.getExtras(),
|
||||
ji.getTransientExtras(), ji.getClipData(), ji.getClipGrantFlags(),
|
||||
isDeadlineExpired, triggeredUris, triggeredAuthorities);
|
||||
mExecutionStartTimeElapsed = SystemClock.elapsedRealtime();
|
||||
|
||||
mVerb = VERB_BINDING;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.job;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.IActivityManager;
|
||||
import android.content.ComponentName;
|
||||
import android.app.job.JobInfo;
|
||||
import android.content.Context;
|
||||
@@ -294,7 +296,7 @@ public class JobStore {
|
||||
addAttributesToJobTag(out, jobStatus);
|
||||
writeConstraintsToXml(out, jobStatus);
|
||||
writeExecutionCriteriaToXml(out, jobStatus);
|
||||
writeBundleToXml(jobStatus.getExtras(), out);
|
||||
writeBundleToXml(jobStatus.getJob().getExtras(), out);
|
||||
out.endTag(null, "job");
|
||||
}
|
||||
out.endTag(null, "job-info");
|
||||
@@ -449,8 +451,11 @@ public class JobStore {
|
||||
synchronized (mLock) {
|
||||
jobs = readJobMapImpl(fis);
|
||||
if (jobs != null) {
|
||||
IActivityManager am = ActivityManager.getService();
|
||||
for (int i=0; i<jobs.size(); i++) {
|
||||
this.jobSet.add(jobs.get(i));
|
||||
JobStatus js = jobs.get(i);
|
||||
js.prepare(am);
|
||||
this.jobSet.add(js);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,19 +17,25 @@
|
||||
package com.android.server.job.controllers;
|
||||
|
||||
import android.app.AppGlobals;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.job.JobInfo;
|
||||
import android.content.ClipData;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Slog;
|
||||
import android.util.TimeUtils;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Uniquely identifies a job internally.
|
||||
@@ -43,6 +49,8 @@ import java.io.PrintWriter;
|
||||
* @hide
|
||||
*/
|
||||
public final class JobStatus {
|
||||
static final String TAG = "JobSchedulerService";
|
||||
|
||||
public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
|
||||
public static final long NO_EARLIEST_RUNTIME = 0L;
|
||||
|
||||
@@ -88,6 +96,9 @@ public final class JobStatus {
|
||||
|
||||
final String tag;
|
||||
|
||||
private IBinder permissionOwner;
|
||||
private boolean prepared;
|
||||
|
||||
/**
|
||||
* Earliest point in the future at which this job will be eligible to run. A value of 0
|
||||
* indicates there is no delay constraint. See {@link #hasTimingDelayConstraint()}.
|
||||
@@ -241,6 +252,93 @@ public final class JobStatus {
|
||||
earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis);
|
||||
}
|
||||
|
||||
public void prepare(IActivityManager am) {
|
||||
if (prepared) {
|
||||
Slog.wtf(TAG, "Already prepared: " + this);
|
||||
return;
|
||||
}
|
||||
prepared = true;
|
||||
final ClipData clip = job.getClipData();
|
||||
if (clip != null) {
|
||||
final int N = clip.getItemCount();
|
||||
for (int i = 0; i < N; i++) {
|
||||
grantItemLocked(am, clip.getItemAt(i), sourceUid, sourcePackageName, sourceUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unprepare(IActivityManager am) {
|
||||
if (!prepared) {
|
||||
Slog.wtf(TAG, "Hasn't been prepared: " + this);
|
||||
return;
|
||||
}
|
||||
prepared = false;
|
||||
if (permissionOwner != null) {
|
||||
final ClipData clip = job.getClipData();
|
||||
if (clip != null) {
|
||||
final int N = clip.getItemCount();
|
||||
for (int i = 0; i < N; i++) {
|
||||
revokeItemLocked(am, clip.getItemAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPrepared() {
|
||||
return prepared;
|
||||
}
|
||||
|
||||
private final void grantUriLocked(IActivityManager am, Uri uri, int sourceUid,
|
||||
String targetPackage, int targetUserId) {
|
||||
try {
|
||||
int sourceUserId = ContentProvider.getUserIdFromUri(uri,
|
||||
UserHandle.getUserId(sourceUid));
|
||||
uri = ContentProvider.getUriWithoutUserId(uri);
|
||||
if (permissionOwner == null) {
|
||||
permissionOwner = am.newUriPermissionOwner("job: " + toShortString());
|
||||
}
|
||||
am.grantUriPermissionFromOwner(permissionOwner, sourceUid, targetPackage,
|
||||
uri, job.getClipGrantFlags(), sourceUserId, targetUserId);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e("JobScheduler", "AM dead");
|
||||
}
|
||||
}
|
||||
|
||||
private final void grantItemLocked(IActivityManager am, ClipData.Item item, int sourceUid,
|
||||
String targetPackage, int targetUserId) {
|
||||
if (item.getUri() != null) {
|
||||
grantUriLocked(am, item.getUri(), sourceUid, targetPackage, targetUserId);
|
||||
}
|
||||
Intent intent = item.getIntent();
|
||||
if (intent != null && intent.getData() != null) {
|
||||
grantUriLocked(am, intent.getData(), sourceUid, targetPackage, targetUserId);
|
||||
}
|
||||
}
|
||||
|
||||
private final void revokeUriLocked(IActivityManager am, Uri uri) {
|
||||
int userId = ContentProvider.getUserIdFromUri(uri,
|
||||
UserHandle.getUserId(Binder.getCallingUid()));
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
uri = ContentProvider.getUriWithoutUserId(uri);
|
||||
am.revokeUriPermissionFromOwner(permissionOwner, uri,
|
||||
job.getClipGrantFlags(), userId);
|
||||
} catch (RemoteException e) {
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
|
||||
private final void revokeItemLocked(IActivityManager am, ClipData.Item item) {
|
||||
if (item.getUri() != null) {
|
||||
revokeUriLocked(am, item.getUri());
|
||||
}
|
||||
Intent intent = item.getIntent();
|
||||
if (intent != null && intent.getData() != null) {
|
||||
revokeUriLocked(am, intent.getData());
|
||||
}
|
||||
}
|
||||
|
||||
public JobInfo getJob() {
|
||||
return job;
|
||||
}
|
||||
@@ -295,14 +393,6 @@ public final class JobStatus {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public PersistableBundle getExtras() {
|
||||
return job.getExtras();
|
||||
}
|
||||
|
||||
public Bundle getTransientExtras() {
|
||||
return job.getTransientExtras();
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return job.getPriority();
|
||||
}
|
||||
@@ -505,22 +595,64 @@ public final class JobStatus {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(hashCode()).substring(0, 3) + ".."
|
||||
+ ":[" + job.getService()
|
||||
+ ",jId=" + job.getId()
|
||||
+ ",u" + getUserId()
|
||||
+ ",suid=" + getSourceUid()
|
||||
+ ",R=(" + formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME)
|
||||
+ "," + formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME) + ")"
|
||||
+ ",N=" + job.getNetworkType() + ",C=" + job.isRequireCharging()
|
||||
+ ",BL=" + job.isRequireBatteryNotLow()
|
||||
+ ",I=" + job.isRequireDeviceIdle()
|
||||
+ ",U=" + (job.getTriggerContentUris() != null)
|
||||
+ ",F=" + numFailures + ",P=" + job.isPersisted()
|
||||
+ ",ANI=" + ((satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) != 0)
|
||||
+ ",DND=" + ((satisfiedConstraints&CONSTRAINT_DEVICE_NOT_DOZING) != 0)
|
||||
+ (isReady() ? "(READY)" : "")
|
||||
+ "]";
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("JobStatus{");
|
||||
sb.append(Integer.toHexString(System.identityHashCode(this)));
|
||||
sb.append(" #");
|
||||
UserHandle.formatUid(sb, callingUid);
|
||||
sb.append("/");
|
||||
sb.append(job.getId());
|
||||
sb.append(' ');
|
||||
sb.append(batteryName);
|
||||
sb.append(" u=");
|
||||
sb.append(getUserId());
|
||||
sb.append(" s=");
|
||||
sb.append(getSourceUid());
|
||||
if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME
|
||||
|| latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) {
|
||||
sb.append(" TIME=");
|
||||
sb.append(formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME));
|
||||
sb.append("-");
|
||||
sb.append(formatRunTime(latestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME));
|
||||
}
|
||||
if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) {
|
||||
sb.append(" NET=");
|
||||
sb.append(job.getNetworkType());
|
||||
}
|
||||
if (job.isRequireCharging()) {
|
||||
sb.append(" CHARGING");
|
||||
}
|
||||
if (job.isRequireBatteryNotLow()) {
|
||||
sb.append(" BATNOTLOW");
|
||||
}
|
||||
if (job.isRequireStorageNotLow()) {
|
||||
sb.append(" STORENOTLOW");
|
||||
}
|
||||
if (job.isRequireDeviceIdle()) {
|
||||
sb.append(" IDLE");
|
||||
}
|
||||
if (job.isPersisted()) {
|
||||
sb.append(" PERSISTED");
|
||||
}
|
||||
if ((satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) == 0) {
|
||||
sb.append(" WAIT:APP_NOT_IDLE");
|
||||
}
|
||||
if ((satisfiedConstraints&CONSTRAINT_DEVICE_NOT_DOZING) == 0) {
|
||||
sb.append(" WAIT:DEV_NOT_DOZING");
|
||||
}
|
||||
if (job.getTriggerContentUris() != null) {
|
||||
sb.append(" URIS=");
|
||||
sb.append(Arrays.toString(job.getTriggerContentUris()));
|
||||
}
|
||||
if (numFailures != 0) {
|
||||
sb.append(" failures=");
|
||||
sb.append(numFailures);
|
||||
}
|
||||
if (isReady()) {
|
||||
sb.append(" READY");
|
||||
}
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String formatRunTime(long runtime, long defaultValue) {
|
||||
@@ -613,8 +745,9 @@ public final class JobStatus {
|
||||
pw.print(" user="); pw.print(getSourceUserId());
|
||||
pw.print(" pkg="); pw.println(getSourcePackageName());
|
||||
if (full) {
|
||||
pw.print(prefix); pw.println("JobInfo:"); pw.print(prefix);
|
||||
pw.print(" Service: "); pw.println(job.getService().flattenToShortString());
|
||||
pw.print(prefix); pw.println("JobInfo:");
|
||||
pw.print(prefix); pw.print(" Service: ");
|
||||
pw.println(job.getService().flattenToShortString());
|
||||
if (job.isPeriodic()) {
|
||||
pw.print(prefix); pw.print(" PERIODIC: interval=");
|
||||
TimeUtils.formatDuration(job.getIntervalMillis(), pw);
|
||||
@@ -654,6 +787,20 @@ public final class JobStatus {
|
||||
pw.println();
|
||||
}
|
||||
}
|
||||
if (job.getExtras() != null && !job.getExtras().maybeIsEmpty()) {
|
||||
pw.print(prefix); pw.print(" Extras: ");
|
||||
pw.println(job.getExtras().toShortString());
|
||||
}
|
||||
if (job.getTransientExtras() != null && !job.getTransientExtras().maybeIsEmpty()) {
|
||||
pw.print(prefix); pw.print(" Transient extras: ");
|
||||
pw.println(job.getTransientExtras().toShortString());
|
||||
}
|
||||
if (job.getClipData() != null) {
|
||||
pw.print(prefix); pw.print(" Clip data: ");
|
||||
StringBuilder b = new StringBuilder(128);
|
||||
job.getClipData().toShortString(b);
|
||||
pw.println(b);
|
||||
}
|
||||
if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) {
|
||||
pw.print(prefix); pw.print(" Network type: "); pw.println(job.getNetworkType());
|
||||
}
|
||||
|
||||
@@ -652,6 +652,11 @@ public class MockContext extends Context {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeUriPermission(String targetPackage, Uri uri, int modeFlags) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
@@ -1658,6 +1658,12 @@ public class BridgeContext extends Context {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeUriPermission(String arg0, Uri arg1, int arg2) {
|
||||
// pass
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcast(Intent arg0) {
|
||||
// pass
|
||||
|
||||
Reference in New Issue
Block a user