Merge "Fix issue #37360626: Apps can schedule alarms (and other things) with temp whitelist" into oc-dev am: c3b938ca5e

am: 8b4c4f09f6

Change-Id: Ia6dd41e08ea31ccc902c4d9ba714e6448898fac4
This commit is contained in:
Dianne Hackborn
2017-05-11 19:34:30 +00:00
committed by android-build-merger
15 changed files with 170 additions and 59 deletions

View File

@@ -51,6 +51,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IUserManager;
import android.os.ParcelFileDescriptor;
import android.os.Process;
@@ -347,7 +348,7 @@ public final class Pm {
private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
@Override
public void send(int code, Intent intent, String resolvedType,
public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
try {
mResult.offer(intent, 5, TimeUnit.SECONDS);

View File

@@ -169,7 +169,8 @@ public abstract class ActivityManagerInternal {
* Sets how long a {@link PendingIntent} can be temporarily whitelist to by bypass restrictions
* such as Power Save mode.
*/
public abstract void setPendingIntentWhitelistDuration(IIntentSender target, long duration);
public abstract void setPendingIntentWhitelistDuration(IIntentSender target,
IBinder whitelistToken, long duration);
/**
* Allow DeviceIdleController to tell us about what apps are whitelisted.

View File

@@ -562,8 +562,8 @@ interface IActivityManager {
void notifyLockedProfile(int userId);
void startConfirmDeviceCredentialIntent(in Intent intent, in Bundle options);
void sendIdleJobTrigger();
int sendIntentSender(in IIntentSender target, int code, in Intent intent,
in String resolvedType, in IIntentReceiver finishedReceiver,
int sendIntentSender(in IIntentSender target, in IBinder whitelistToken, int code,
in Intent intent, in String resolvedType, in IIntentReceiver finishedReceiver,
in String requiredPermission, in Bundle options);

View File

@@ -42,8 +42,10 @@ import android.media.PlayerBase;
import android.media.session.MediaSession;
import android.net.Uri;
import android.os.BadParcelableException;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -834,6 +836,22 @@ public class Notification implements Parcelable
*/
public ArraySet<PendingIntent> allPendingIntents;
/**
* Token identifying the notification that is applying doze/bgcheck whitelisting to the
* pending intents inside of it, so only those will get the behavior.
*
* @hide
*/
static public IBinder whitelistToken;
/**
* Must be set by a process to start associating tokens with Notification objects
* coming in to it. This is set by NotificationManagerService.
*
* @hide
*/
static public IBinder processWhitelistToken;
/**
* {@link #extras} key: this is the title of the notification,
* as supplied to {@link Builder#setContentTitle(CharSequence)}.
@@ -1823,6 +1841,13 @@ public class Notification implements Parcelable
{
int version = parcel.readInt();
whitelistToken = parcel.readStrongBinder();
if (whitelistToken == null) {
whitelistToken = processWhitelistToken;
}
// Propagate this token to all pending intents that are unmarshalled from the parcel.
parcel.setClassCookie(PendingIntent.class, whitelistToken);
when = parcel.readLong();
creationTime = parcel.readLong();
if (parcel.readInt() != 0) {
@@ -1929,6 +1954,7 @@ public class Notification implements Parcelable
* @hide
*/
public void cloneInto(Notification that, boolean heavy) {
that.whitelistToken = this.whitelistToken;
that.when = this.when;
that.creationTime = this.creationTime;
that.mSmallIcon = this.mSmallIcon;
@@ -2158,6 +2184,7 @@ public class Notification implements Parcelable
private void writeToParcelImpl(Parcel parcel, int flags) {
parcel.writeInt(1);
parcel.writeStrongBinder(whitelistToken);
parcel.writeLong(when);
parcel.writeLong(creationTime);
if (mSmallIcon == null && icon != 0) {

View File

@@ -93,6 +93,7 @@ import java.lang.annotation.RetentionPolicy;
*/
public final class PendingIntent implements Parcelable {
private final IIntentSender mTarget;
private IBinder mWhitelistToken;
/** @hide */
@IntDef(flag = true,
@@ -656,7 +657,7 @@ public final class PendingIntent implements Parcelable {
*
*/
public IntentSender getIntentSender() {
return new IntentSender(mTarget);
return new IntentSender(mTarget, mWhitelistToken);
}
/**
@@ -870,7 +871,7 @@ public final class PendingIntent implements Parcelable {
intent.resolveTypeIfNeeded(context.getContentResolver())
: null;
int res = ActivityManager.getService().sendIntentSender(
mTarget, code, intent, resolvedType,
mTarget, mWhitelistToken, code, intent, resolvedType,
onFinished != null
? new FinishedDispatcher(this, onFinished, handler)
: null,
@@ -1085,7 +1086,9 @@ public final class PendingIntent implements Parcelable {
= new Parcelable.Creator<PendingIntent>() {
public PendingIntent createFromParcel(Parcel in) {
IBinder target = in.readStrongBinder();
return target != null ? new PendingIntent(target) : null;
return target != null
? new PendingIntent(target, in.getClassCookie(PendingIntent.class))
: null;
}
public PendingIntent[] newArray(int size) {
@@ -1108,31 +1111,39 @@ public final class PendingIntent implements Parcelable {
}
/**
* Convenience function for reading either a Messenger or null pointer from
* a Parcel. You must have previously written the Messenger with
* Convenience function for reading either a PendingIntent or null pointer from
* a Parcel. You must have previously written the PendingIntent with
* {@link #writePendingIntentOrNullToParcel}.
*
* @param in The Parcel containing the written Messenger.
* @param in The Parcel containing the written PendingIntent.
*
* @return Returns the Messenger read from the Parcel, or null if null had
* @return Returns the PendingIntent read from the Parcel, or null if null had
* been written.
*/
@Nullable
public static PendingIntent readPendingIntentOrNullFromParcel(@NonNull Parcel in) {
IBinder b = in.readStrongBinder();
return b != null ? new PendingIntent(b) : null;
return b != null ? new PendingIntent(b, in.getClassCookie(PendingIntent.class)) : null;
}
/*package*/ PendingIntent(IIntentSender target) {
mTarget = target;
}
/*package*/ PendingIntent(IBinder target) {
/*package*/ PendingIntent(IBinder target, Object cookie) {
mTarget = IIntentSender.Stub.asInterface(target);
if (cookie != null) {
mWhitelistToken = (IBinder)cookie;
}
}
/** @hide */
public IIntentSender getTarget() {
return mTarget;
}
/** @hide */
public IBinder getWhitelistToken() {
return mWhitelistToken;
}
}

View File

@@ -22,6 +22,6 @@ import android.os.Bundle;
/** @hide */
oneway interface IIntentSender {
void send(int code, in Intent intent, String resolvedType,
void send(int code, in Intent intent, String resolvedType, in IBinder whitelistToken,
IIntentReceiver finishedReceiver, String requiredPermission, in Bundle options);
}

View File

@@ -56,6 +56,7 @@ import android.util.AndroidException;
*/
public class IntentSender implements Parcelable {
private final IIntentSender mTarget;
IBinder mWhitelistToken;
/**
* Exception thrown when trying to send through a PendingIntent that
@@ -187,7 +188,7 @@ public class IntentSender implements Parcelable {
String resolvedType = intent != null ?
intent.resolveTypeIfNeeded(context.getContentResolver())
: null;
int res = ActivityManager.getService().sendIntentSender(mTarget,
int res = ActivityManager.getService().sendIntentSender(mTarget, mWhitelistToken,
code, intent, resolvedType,
onFinished != null
? new FinishedDispatcher(this, onFinished, handler)
@@ -364,6 +365,12 @@ public class IntentSender implements Parcelable {
mTarget = target;
}
/** @hide */
public IntentSender(IIntentSender target, IBinder whitelistToken) {
mTarget = target;
mWhitelistToken = whitelistToken;
}
/** @hide */
public IntentSender(IBinder target) {
mTarget = IIntentSender.Stub.asInterface(target);

View File

@@ -1548,6 +1548,7 @@ public class BaseBundle {
Parcel p = Parcel.obtain();
p.setDataPosition(0);
p.appendFrom(parcel, offset, length);
p.adoptClassCookies(parcel);
if (DEBUG) Log.d(TAG, "Retrieving " + Integer.toHexString(System.identityHashCode(this))
+ ": " + length + " bundle bytes starting at " + offset);
p.setDataPosition(0);

View File

@@ -204,6 +204,8 @@ public final class Parcel {
private boolean mOwnsNativeParcelObject;
private long mNativeSize;
private ArrayMap<Class, Object> mClassCookies;
private RuntimeException mStack;
private static final int POOL_SIZE = 6;
@@ -497,6 +499,24 @@ public final class Parcel {
return nativeCompareData(mNativePtr, other.mNativePtr);
}
/** @hide */
public final void setClassCookie(Class clz, Object cookie) {
if (mClassCookies == null) {
mClassCookies = new ArrayMap<>();
}
mClassCookies.put(clz, cookie);
}
/** @hide */
public final Object getClassCookie(Class clz) {
return mClassCookies != null ? mClassCookies.get(clz) : null;
}
/** @hide */
public final void adoptClassCookies(Parcel from) {
mClassCookies = from.mClassCookies;
}
/**
* Report whether the parcel contains any marshalled file descriptors.
*/

View File

@@ -4578,7 +4578,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mAppSwitchesAllowedTime = 0;
}
}
int ret = pir.sendInner(0, fillInIntent, resolvedType, null, null,
int ret = pir.sendInner(0, fillInIntent, resolvedType, null, null, null,
resultTo, resultWho, requestCode, flagsMask, flagsValues, bOptions, null);
return ret;
}
@@ -7484,11 +7484,12 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
public int sendIntentSender(IIntentSender target, int code, Intent intent, String resolvedType,
public int sendIntentSender(IIntentSender target, IBinder whitelistToken, int code,
Intent intent, String resolvedType,
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
if (target instanceof PendingIntentRecord) {
return ((PendingIntentRecord)target).sendWithResult(code, intent, resolvedType,
finishedReceiver, requiredPermission, options);
whitelistToken, finishedReceiver, requiredPermission, options);
} else {
if (intent == null) {
// Weird case: someone has given us their own custom IIntentSender, and now
@@ -7500,7 +7501,8 @@ public class ActivityManagerService extends IActivityManager.Stub
intent = new Intent(Intent.ACTION_MAIN);
}
try {
target.send(code, intent, resolvedType, null, requiredPermission, options);
target.send(code, intent, resolvedType, whitelistToken, null,
requiredPermission, options);
} catch (RemoteException e) {
}
// Platform code can rely on getting a result back when the send is done, but if
@@ -7797,11 +7799,15 @@ public class ActivityManagerService extends IActivityManager.Stub
// be guarded by permission checking.
int getUidState(int uid) {
synchronized (this) {
UidRecord uidRec = mActiveUids.get(uid);
return uidRec == null ? ActivityManager.PROCESS_STATE_NONEXISTENT : uidRec.curProcState;
return getUidStateLocked(uid);
}
}
int getUidStateLocked(int uid) {
UidRecord uidRec = mActiveUids.get(uid);
return uidRec == null ? ActivityManager.PROCESS_STATE_NONEXISTENT : uidRec.curProcState;
}
@Override
public boolean isInMultiWindowMode(IBinder token) {
final long origId = Binder.clearCallingIdentity();
@@ -23617,12 +23623,13 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
public void setPendingIntentWhitelistDuration(IIntentSender target, long duration) {
public void setPendingIntentWhitelistDuration(IIntentSender target, IBinder whitelistToken,
long duration) {
if (!(target instanceof PendingIntentRecord)) {
Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target);
return;
}
((PendingIntentRecord) target).setWhitelistDurationLocked(duration);
((PendingIntentRecord) target).setWhitelistDurationLocked(whitelistToken, duration);
}
@Override

View File

@@ -22,11 +22,8 @@ import android.app.AppGlobals;
import android.app.IActivityContainer;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IInstrumentationWatcher;
import android.app.IStopUserCallback;
import android.app.Instrumentation;
import android.app.ProfilerInfo;
import android.app.UiAutomationConnection;
import android.app.WaitResult;
import android.app.usage.ConfigurationStats;
import android.app.usage.IUsageStatsManager;
@@ -37,7 +34,6 @@ import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;

View File

@@ -4719,7 +4719,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
checkEmbeddedAllowedInner(userId, pendingIntent.key.requestIntent,
pendingIntent.key.requestResolvedType);
return pendingIntent.sendInner(0, null, null, null, null, null, null, 0,
return pendingIntent.sendInner(0, null, null, null, null, null, null, null, 0,
FORCE_NEW_TASK_FLAGS, FORCE_NEW_TASK_FLAGS, null, this);
}

View File

@@ -32,6 +32,7 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.TransactionTooLargeException;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Slog;
import android.util.TimeUtils;
@@ -51,7 +52,7 @@ final class PendingIntentRecord extends IIntentSender.Stub {
final WeakReference<PendingIntentRecord> ref;
boolean sent = false;
boolean canceled = false;
private long whitelistDuration = 0;
private ArrayMap<IBinder, Long> whitelistDuration;
private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
String stringName;
@@ -194,8 +195,19 @@ final class PendingIntentRecord extends IIntentSender.Stub {
ref = new WeakReference<PendingIntentRecord>(this);
}
void setWhitelistDurationLocked(long duration) {
this.whitelistDuration = duration;
void setWhitelistDurationLocked(IBinder whitelistToken, long duration) {
if (duration > 0) {
if (whitelistDuration == null) {
whitelistDuration = new ArrayMap<>();
}
whitelistDuration.put(whitelistToken, duration);
} else if (whitelistDuration != null) {
whitelistDuration.remove(whitelistToken);
if (whitelistDuration.size() <= 0) {
whitelistDuration = null;
}
}
this.stringName = null;
}
@@ -219,19 +231,20 @@ final class PendingIntentRecord extends IIntentSender.Stub {
return listeners;
}
public void send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
String requiredPermission, Bundle options) {
sendInner(code, intent, resolvedType, finishedReceiver,
requiredPermission, null, null, 0, 0, 0, options, null);
}
public int sendWithResult(int code, Intent intent, String resolvedType,
public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
return sendInner(code, intent, resolvedType, finishedReceiver,
sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
requiredPermission, null, null, 0, 0, 0, options, null);
}
int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
public int sendWithResult(int code, Intent intent, String resolvedType, IBinder whitelistToken,
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
return sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
requiredPermission, null, null, 0, 0, 0, options, null);
}
int sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken,
IIntentReceiver finishedReceiver,
String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
if (intent != null) intent.setDefusable(true);
@@ -276,20 +289,29 @@ final class PendingIntentRecord extends IIntentSender.Stub {
final long origId = Binder.clearCallingIdentity();
if (whitelistDuration > 0) {
StringBuilder tag = new StringBuilder(64);
tag.append("pendingintent:");
UserHandle.formatUid(tag, callingUid);
tag.append(":");
if (finalIntent.getAction() != null) {
tag.append(finalIntent.getAction());
} else if (finalIntent.getComponent() != null) {
finalIntent.getComponent().appendShortString(tag);
} else if (finalIntent.getData() != null) {
tag.append(finalIntent.getData());
if (whitelistDuration != null) {
Long duration = whitelistDuration.get(whitelistToken);
if (duration != null) {
int procState = owner.getUidState(callingUid);
if (!ActivityManager.isProcStateBackground(procState)) {
StringBuilder tag = new StringBuilder(64);
tag.append("pendingintent:");
UserHandle.formatUid(tag, callingUid);
tag.append(":");
if (finalIntent.getAction() != null) {
tag.append(finalIntent.getAction());
} else if (finalIntent.getComponent() != null) {
finalIntent.getComponent().appendShortString(tag);
} else if (finalIntent.getData() != null) {
tag.append(finalIntent.getData());
}
owner.tempWhitelistForPendingIntentLocked(callingPid,
callingUid, uid, duration, tag.toString());
} else {
Slog.w(TAG, "Not doing whitelist " + this + ": caller state="
+ procState);
}
}
owner.tempWhitelistForPendingIntentLocked(callingPid,
callingUid, uid, whitelistDuration, tag.toString());
}
boolean sendFinish = finishedReceiver != null;
@@ -425,10 +447,17 @@ final class PendingIntentRecord extends IIntentSender.Stub {
pw.print(prefix); pw.print("sent="); pw.print(sent);
pw.print(" canceled="); pw.println(canceled);
}
if (whitelistDuration != 0) {
if (whitelistDuration != null) {
pw.print(prefix);
pw.print("whitelistDuration=");
TimeUtils.formatDuration(whitelistDuration, pw);
for (int i = 0; i < whitelistDuration.size(); i++) {
if (i != 0) {
pw.print(", ");
}
pw.print(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
pw.print(":");
TimeUtils.formatDuration(whitelistDuration.valueAt(i), pw);
}
pw.println();
}
if (mCancelCallbacks != null) {
@@ -451,9 +480,16 @@ final class PendingIntentRecord extends IIntentSender.Stub {
sb.append(key.packageName);
sb.append(' ');
sb.append(key.typeName());
if (whitelistDuration > 0) {
if (whitelistDuration != null) {
sb.append( " (whitelist: ");
TimeUtils.formatDuration(whitelistDuration, sb);
for (int i = 0; i < whitelistDuration.size(); i++) {
if (i != 0) {
sb.append(",");
}
sb.append(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
sb.append(":");
TimeUtils.formatDuration(whitelistDuration.valueAt(i), sb);
}
sb.append(")");
}
sb.append('}');

View File

@@ -344,6 +344,7 @@ public class NotificationManagerService extends SystemService {
private static final int MY_UID = Process.myUid();
private static final int MY_PID = Process.myPid();
private static final IBinder WHITELIST_TOKEN = new Binder();
private RankingHandler mRankingHandler;
private long mLastOverRateLogTime;
private float mMaxPackageEnqueueRate = DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE;
@@ -983,6 +984,7 @@ public class NotificationManagerService extends SystemService {
public NotificationManagerService(Context context) {
super(context);
Notification.processWhitelistToken = WHITELIST_TOKEN;
}
// TODO - replace these methods with a single VisibleForTesting constructor
@@ -3256,7 +3258,8 @@ public class NotificationManagerService extends SystemService {
for (int i = 0; i < intentCount; i++) {
PendingIntent pendingIntent = notification.allPendingIntents.valueAt(i);
if (pendingIntent != null) {
am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(), duration);
am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(),
WHITELIST_TOKEN, duration);
}
}
}

View File

@@ -48,6 +48,7 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.SystemProperties;
@@ -1686,7 +1687,7 @@ class PackageManagerShellCommand extends ShellCommand {
private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
@Override
public void send(int code, Intent intent, String resolvedType,
public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
try {
mResult.offer(intent, 5, TimeUnit.SECONDS);