Merge "Inform UsageStatsManager about broadcast-dispatched events."
This commit is contained in:
committed by
Android (Google) Code Review
commit
6ec5f7fd7f
@@ -744,6 +744,7 @@ package android.app {
|
||||
method public void clearRequireCompatChange();
|
||||
method public boolean isPendingIntentBackgroundActivityLaunchAllowed();
|
||||
method public static android.app.BroadcastOptions makeBasic();
|
||||
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from=0) long);
|
||||
method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
|
||||
method public void setDontSendToRestrictedApps(boolean);
|
||||
method public void setPendingIntentBackgroundActivityLaunchAllowed(boolean);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.app;
|
||||
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
@@ -52,6 +53,7 @@ public class BroadcastOptions extends ComponentOptions {
|
||||
private String[] mRequireNoneOfPermissions;
|
||||
private long mRequireCompatChangeId = CHANGE_INVALID;
|
||||
private boolean mRequireCompatChangeEnabled = true;
|
||||
private long mIdForResponseEvent;
|
||||
|
||||
/**
|
||||
* Change ID which is invalid.
|
||||
@@ -164,6 +166,12 @@ public class BroadcastOptions extends ComponentOptions {
|
||||
public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED =
|
||||
PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
|
||||
|
||||
/**
|
||||
* Corresponds to {@link #recordResponseEventWhileInBackground(long)}.
|
||||
*/
|
||||
private static final String KEY_ID_FOR_RESPONSE_EVENT =
|
||||
"android:broadcast.idForResponseEvent";
|
||||
|
||||
public static BroadcastOptions makeBasic() {
|
||||
BroadcastOptions opts = new BroadcastOptions();
|
||||
return opts;
|
||||
@@ -198,6 +206,7 @@ public class BroadcastOptions extends ComponentOptions {
|
||||
mRequireNoneOfPermissions = opts.getStringArray(KEY_REQUIRE_NONE_OF_PERMISSIONS);
|
||||
mRequireCompatChangeId = opts.getLong(KEY_REQUIRE_COMPAT_CHANGE_ID, CHANGE_INVALID);
|
||||
mRequireCompatChangeEnabled = opts.getBoolean(KEY_REQUIRE_COMPAT_CHANGE_ENABLED, true);
|
||||
mIdForResponseEvent = opts.getLong(KEY_ID_FOR_RESPONSE_EVENT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -510,6 +519,28 @@ public class BroadcastOptions extends ComponentOptions {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether events (such as posting a notification) originating from an app after it
|
||||
* receives the broadcast while in background should be recorded as responses to the broadcast.
|
||||
*
|
||||
* @param id ID to be used for the response events corresponding to this broadcast. If the
|
||||
* value is {@code 0} (default), then response events will not be recorded. Otherwise,
|
||||
* they will be recorded with the ID provided.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
|
||||
public void recordResponseEventWhileInBackground(@IntRange(from = 0) long id) {
|
||||
mIdForResponseEvent = id;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@IntRange(from = 0)
|
||||
public long getIdForResponseEvent() {
|
||||
return mIdForResponseEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the created options as a Bundle, which can be passed to
|
||||
* {@link android.content.Context#sendBroadcast(android.content.Intent)
|
||||
@@ -549,6 +580,9 @@ public class BroadcastOptions extends ComponentOptions {
|
||||
b.putLong(KEY_REQUIRE_COMPAT_CHANGE_ID, mRequireCompatChangeId);
|
||||
b.putBoolean(KEY_REQUIRE_COMPAT_CHANGE_ENABLED, mRequireCompatChangeEnabled);
|
||||
}
|
||||
if (mIdForResponseEvent != 0) {
|
||||
b.putLong(KEY_ID_FOR_RESPONSE_EVENT, mIdForResponseEvent);
|
||||
}
|
||||
return b.isEmpty() ? null : b;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS
|
||||
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST;
|
||||
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AppGlobals;
|
||||
@@ -37,6 +38,7 @@ import android.app.IApplicationThread;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.RemoteServiceException.CannotDeliverBroadcastException;
|
||||
import android.app.usage.UsageEvents.Event;
|
||||
import android.app.usage.UsageStatsManagerInternal;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.IIntentReceiver;
|
||||
@@ -69,6 +71,7 @@ import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -325,6 +328,7 @@ public final class BroadcastQueue {
|
||||
mService.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
|
||||
|
||||
// Tell the application to launch this receiver.
|
||||
maybeReportBroadcastDispatchedEventLocked(r);
|
||||
r.intent.setComponent(r.curComponent);
|
||||
|
||||
boolean started = false;
|
||||
@@ -917,6 +921,7 @@ public final class BroadcastQueue {
|
||||
r.receiverTime = SystemClock.uptimeMillis();
|
||||
maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
|
||||
maybeScheduleTempAllowlistLocked(filter.owningUid, r, r.options);
|
||||
maybeReportBroadcastDispatchedEventLocked(r);
|
||||
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
|
||||
new Intent(r.intent), r.resultCode, r.resultData,
|
||||
r.resultExtras, r.ordered, r.initialSticky, r.userId);
|
||||
@@ -1831,6 +1836,45 @@ public final class BroadcastQueue {
|
||||
mPendingBroadcastRecvIndex = recIdx;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private String getTargetPackage(BroadcastRecord r) {
|
||||
if (r.intent == null) {
|
||||
return null;
|
||||
}
|
||||
if (r.intent.getPackage() != null) {
|
||||
return r.intent.getPackage();
|
||||
} else if (r.intent.getComponent() != null) {
|
||||
return r.intent.getComponent().getPackageName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void maybeReportBroadcastDispatchedEventLocked(BroadcastRecord r) {
|
||||
final String targetPackage = getTargetPackage(r);
|
||||
// Ignore non-explicit broadcasts
|
||||
if (targetPackage == null) {
|
||||
return;
|
||||
}
|
||||
// TODO (206518114): Only allow apps with ACCESS_PACKAGE_USAGE_STATS to set
|
||||
// getIdForResponseEvent.
|
||||
if (r.options == null || r.options.getIdForResponseEvent() <= 0) {
|
||||
return;
|
||||
}
|
||||
// TODO (206518114): Only report this event when the broadcast is dispatched while the app
|
||||
// is in the background state.
|
||||
getUsageStatsManagerInternal().reportBroadcastDispatched(
|
||||
r.callingUid, targetPackage, UserHandle.of(r.userId),
|
||||
r.options.getIdForResponseEvent(), SystemClock.elapsedRealtime());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private UsageStatsManagerInternal getUsageStatsManagerInternal() {
|
||||
final UsageStatsManagerInternal usageStatsManagerInternal =
|
||||
LocalServices.getService(UsageStatsManagerInternal.class);
|
||||
return usageStatsManagerInternal;
|
||||
}
|
||||
|
||||
private boolean noteOpForManifestReceiver(int appOp, BroadcastRecord r, ResolveInfo info,
|
||||
ComponentName component) {
|
||||
if (ArrayUtils.isEmpty(info.activityInfo.attributionTags)) {
|
||||
|
||||
Reference in New Issue
Block a user