Loading services/core/java/com/android/server/am/ActivityManagerService.java +36 −3 Original line number Diff line number Diff line Loading @@ -15312,12 +15312,17 @@ public class ActivityManagerService extends IActivityManager.Stub final int cookie = traceBroadcastIntentBegin(intent, resultTo, ordered, sticky, callingUid, realCallingUid, userId); try { final BroadcastSentEventRecord broadcastSentEventRecord = new BroadcastSentEventRecord(); final int res = broadcastIntentLockedTraced(callerApp, callerPackage, callerFeatureId, intent, resolvedType, resultToApp, resultTo, resultCode, resultData, resultExtras, requiredPermissions, excludedPermissions, excludedPackages, appOp, BroadcastOptions.fromBundleNullable(bOptions), ordered, sticky, callingPid, callingUid, realCallingUid, realCallingPid, userId, backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver); backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver, broadcastSentEventRecord); broadcastSentEventRecord.setResult(res); broadcastSentEventRecord.logToStatsd(); return res; } finally { traceBroadcastIntentEnd(cookie); Loading Loading @@ -15365,7 +15370,8 @@ public class ActivityManagerService extends IActivityManager.Stub int callingUid, int realCallingUid, int realCallingPid, int userId, BackgroundStartPrivileges backgroundStartPrivileges, @Nullable int[] broadcastAllowList, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) { @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, @NonNull BroadcastSentEventRecord broadcastSentEventRecord) { // Ensure all internal loopers are registered for idle checks BroadcastLoopers.addMyLooper(); Loading Loading @@ -15398,6 +15404,17 @@ public class ActivityManagerService extends IActivityManager.Stub } intent = new Intent(intent); broadcastSentEventRecord.setIntent(intent); broadcastSentEventRecord.setOriginalIntentFlags(intent.getFlags()); broadcastSentEventRecord.setSenderUid(callingUid); broadcastSentEventRecord.setRealSenderUid(realCallingUid); broadcastSentEventRecord.setSticky(sticky); broadcastSentEventRecord.setOrdered(ordered); broadcastSentEventRecord.setResultRequested(resultTo != null); final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid); broadcastSentEventRecord.setSenderProcState(callerAppProcessState); broadcastSentEventRecord.setSenderUidState(getRealUidStateLocked(callerApp, realCallingPid)); final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid); // Instant Apps cannot use FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS Loading Loading @@ -15891,7 +15908,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid); // Add to the sticky list if requested. if (sticky) { if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, Loading Loading @@ -16131,6 +16147,7 @@ public class ActivityManagerService extends IActivityManager.Stub ordered, sticky, false, userId, backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver, callerAppProcessState); broadcastSentEventRecord.setBroadcastRecord(r); if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r); queue.enqueueBroadcastLocked(r); Loading Loading @@ -16187,6 +16204,22 @@ public class ActivityManagerService extends IActivityManager.Stub return PROCESS_STATE_NONEXISTENT; } @GuardedBy("this") private int getRealUidStateLocked(ProcessRecord app, int pid) { if (app == null) { synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); } } if (app != null && app.getThread() != null && !app.isKilled()) { final UidRecord uidRecord = app.getUidRecord(); if (uidRecord != null) { return uidRecord.getCurProcState(); } } return PROCESS_STATE_NONEXISTENT; } @VisibleForTesting ArrayList<StickyBroadcast> getStickyBroadcastsForTest(String action, int userId) { synchronized (mStickyBroadcasts) { services/core/java/com/android/server/am/BroadcastRecord.java +41 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import android.os.Bundle; import android.os.SystemClock; import android.os.UserHandle; import android.util.ArrayMap; import android.util.IntArray; import android.util.PrintWriterPrinter; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; Loading Loading @@ -940,6 +941,46 @@ final class BroadcastRecord extends Binder { return type; } int[] calculateTypesForLogging() { final IntArray types = new IntArray(); if (isForeground()) { types.add(BROADCAST_TYPE_FOREGROUND); } else { types.add(BROADCAST_TYPE_BACKGROUND); } if (alarm) { types.add(BROADCAST_TYPE_ALARM); } if (interactive) { types.add(BROADCAST_TYPE_INTERACTIVE); } if (ordered) { types.add(BROADCAST_TYPE_ORDERED); } if (prioritized) { types.add(BROADCAST_TYPE_PRIORITIZED); } if (resultTo != null) { types.add(BROADCAST_TYPE_RESULT_TO); } if (deferUntilActive) { types.add(BROADCAST_TYPE_DEFERRABLE_UNTIL_ACTIVE); } if (pushMessage) { types.add(BROADCAST_TYPE_PUSH_MESSAGE); } if (pushMessageOverQuota) { types.add(BROADCAST_TYPE_PUSH_MESSAGE_OVER_QUOTA); } if (sticky) { types.add(BROADCAST_TYPE_STICKY); } if (initialSticky) { types.add(BROADCAST_TYPE_INITIAL_STICKY); } return types.toArray(); } public BroadcastRecord maybeStripForHistory() { if (!intent.canStripForHistory()) { return this; Loading services/core/java/com/android/server/am/BroadcastSentEventRecord.java 0 → 100644 +134 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.am; import static android.app.AppProtoEnums.BROADCAST_TYPE_ORDERED; import static android.app.AppProtoEnums.BROADCAST_TYPE_RESULT_TO; import static android.app.AppProtoEnums.BROADCAST_TYPE_STICKY; import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT; import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__FAILED_STICKY_CANT_HAVE_PERMISSION; import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__FAILED_USER_STOPPED; import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__SUCCESS; import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__UNKNOWN; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Intent; import android.util.IntArray; import com.android.internal.util.FrameworkStatsLog; final class BroadcastSentEventRecord { @NonNull private Intent mIntent; private int mOriginalIntentFlags; private int mSenderUid; private int mRealSenderUid; private boolean mSticky; private boolean mOrdered; private boolean mResultRequested; private int mSenderProcState; private int mSenderUidState; @Nullable private BroadcastRecord mBroadcastRecord; private int mResult; public void setIntent(@NonNull Intent intent) { mIntent = intent; } public void setSenderUid(int uid) { mSenderUid = uid; } public void setRealSenderUid(int uid) { mRealSenderUid = uid; } public void setOriginalIntentFlags(int flags) { mOriginalIntentFlags = flags; } public void setSticky(boolean sticky) { mSticky = sticky; } public void setOrdered(boolean ordered) { mOrdered = ordered; } public void setResultRequested(boolean resultRequested) { mResultRequested = resultRequested; } public void setSenderProcState(int procState) { mSenderProcState = procState; } public void setSenderUidState(int procState) { mSenderUidState = procState; } public void setBroadcastRecord(@NonNull BroadcastRecord record) { mBroadcastRecord = record; } public void setResult(int result) { mResult = result; } public void logToStatsd() { if (Flags.logBroadcastSentEvent()) { int loggingResult = switch (mResult) { case ActivityManager.BROADCAST_SUCCESS -> BROADCAST_SENT__RESULT__SUCCESS; case ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION -> BROADCAST_SENT__RESULT__FAILED_STICKY_CANT_HAVE_PERMISSION; case ActivityManager.BROADCAST_FAILED_USER_STOPPED -> BROADCAST_SENT__RESULT__FAILED_USER_STOPPED; default -> BROADCAST_SENT__RESULT__UNKNOWN; }; int[] types = calculateTypesForLogging(); FrameworkStatsLog.write(BROADCAST_SENT, mIntent.getAction(), mIntent.getFlags(), mOriginalIntentFlags, mSenderUid, mRealSenderUid, mIntent.getPackage() != null, mIntent.getComponent() != null, mBroadcastRecord != null ? mBroadcastRecord.receivers.size() : 0, loggingResult, mBroadcastRecord != null ? mBroadcastRecord.getDeliveryGroupPolicy() : 0, ActivityManager.processStateAmToProto(mSenderProcState), ActivityManager.processStateAmToProto(mSenderUidState), types); } } private int[] calculateTypesForLogging() { if (mBroadcastRecord != null) { return mBroadcastRecord.calculateTypesForLogging(); } else { final IntArray types = new IntArray(); if (mSticky) { types.add(BROADCAST_TYPE_STICKY); } if (mOrdered) { types.add(BROADCAST_TYPE_ORDERED); } if (mResultRequested) { types.add(BROADCAST_TYPE_RESULT_TO); } return types.toArray(); } } } services/core/java/com/android/server/am/flags.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -184,3 +184,14 @@ flag { description: "Defer submitting binder calls to paused processes." bug: "327038797" } flag { name: "log_broadcast_sent_event" namespace: "backstage_power" description: "Log the broadcast send event to Statsd" bug: "355261986" is_fixed_read_only: true metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file Loading
services/core/java/com/android/server/am/ActivityManagerService.java +36 −3 Original line number Diff line number Diff line Loading @@ -15312,12 +15312,17 @@ public class ActivityManagerService extends IActivityManager.Stub final int cookie = traceBroadcastIntentBegin(intent, resultTo, ordered, sticky, callingUid, realCallingUid, userId); try { final BroadcastSentEventRecord broadcastSentEventRecord = new BroadcastSentEventRecord(); final int res = broadcastIntentLockedTraced(callerApp, callerPackage, callerFeatureId, intent, resolvedType, resultToApp, resultTo, resultCode, resultData, resultExtras, requiredPermissions, excludedPermissions, excludedPackages, appOp, BroadcastOptions.fromBundleNullable(bOptions), ordered, sticky, callingPid, callingUid, realCallingUid, realCallingPid, userId, backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver); backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver, broadcastSentEventRecord); broadcastSentEventRecord.setResult(res); broadcastSentEventRecord.logToStatsd(); return res; } finally { traceBroadcastIntentEnd(cookie); Loading Loading @@ -15365,7 +15370,8 @@ public class ActivityManagerService extends IActivityManager.Stub int callingUid, int realCallingUid, int realCallingPid, int userId, BackgroundStartPrivileges backgroundStartPrivileges, @Nullable int[] broadcastAllowList, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) { @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, @NonNull BroadcastSentEventRecord broadcastSentEventRecord) { // Ensure all internal loopers are registered for idle checks BroadcastLoopers.addMyLooper(); Loading Loading @@ -15398,6 +15404,17 @@ public class ActivityManagerService extends IActivityManager.Stub } intent = new Intent(intent); broadcastSentEventRecord.setIntent(intent); broadcastSentEventRecord.setOriginalIntentFlags(intent.getFlags()); broadcastSentEventRecord.setSenderUid(callingUid); broadcastSentEventRecord.setRealSenderUid(realCallingUid); broadcastSentEventRecord.setSticky(sticky); broadcastSentEventRecord.setOrdered(ordered); broadcastSentEventRecord.setResultRequested(resultTo != null); final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid); broadcastSentEventRecord.setSenderProcState(callerAppProcessState); broadcastSentEventRecord.setSenderUidState(getRealUidStateLocked(callerApp, realCallingPid)); final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid); // Instant Apps cannot use FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS Loading Loading @@ -15891,7 +15908,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid); // Add to the sticky list if requested. if (sticky) { if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, Loading Loading @@ -16131,6 +16147,7 @@ public class ActivityManagerService extends IActivityManager.Stub ordered, sticky, false, userId, backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver, callerAppProcessState); broadcastSentEventRecord.setBroadcastRecord(r); if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r); queue.enqueueBroadcastLocked(r); Loading Loading @@ -16187,6 +16204,22 @@ public class ActivityManagerService extends IActivityManager.Stub return PROCESS_STATE_NONEXISTENT; } @GuardedBy("this") private int getRealUidStateLocked(ProcessRecord app, int pid) { if (app == null) { synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); } } if (app != null && app.getThread() != null && !app.isKilled()) { final UidRecord uidRecord = app.getUidRecord(); if (uidRecord != null) { return uidRecord.getCurProcState(); } } return PROCESS_STATE_NONEXISTENT; } @VisibleForTesting ArrayList<StickyBroadcast> getStickyBroadcastsForTest(String action, int userId) { synchronized (mStickyBroadcasts) {
services/core/java/com/android/server/am/BroadcastRecord.java +41 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import android.os.Bundle; import android.os.SystemClock; import android.os.UserHandle; import android.util.ArrayMap; import android.util.IntArray; import android.util.PrintWriterPrinter; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; Loading Loading @@ -940,6 +941,46 @@ final class BroadcastRecord extends Binder { return type; } int[] calculateTypesForLogging() { final IntArray types = new IntArray(); if (isForeground()) { types.add(BROADCAST_TYPE_FOREGROUND); } else { types.add(BROADCAST_TYPE_BACKGROUND); } if (alarm) { types.add(BROADCAST_TYPE_ALARM); } if (interactive) { types.add(BROADCAST_TYPE_INTERACTIVE); } if (ordered) { types.add(BROADCAST_TYPE_ORDERED); } if (prioritized) { types.add(BROADCAST_TYPE_PRIORITIZED); } if (resultTo != null) { types.add(BROADCAST_TYPE_RESULT_TO); } if (deferUntilActive) { types.add(BROADCAST_TYPE_DEFERRABLE_UNTIL_ACTIVE); } if (pushMessage) { types.add(BROADCAST_TYPE_PUSH_MESSAGE); } if (pushMessageOverQuota) { types.add(BROADCAST_TYPE_PUSH_MESSAGE_OVER_QUOTA); } if (sticky) { types.add(BROADCAST_TYPE_STICKY); } if (initialSticky) { types.add(BROADCAST_TYPE_INITIAL_STICKY); } return types.toArray(); } public BroadcastRecord maybeStripForHistory() { if (!intent.canStripForHistory()) { return this; Loading
services/core/java/com/android/server/am/BroadcastSentEventRecord.java 0 → 100644 +134 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.am; import static android.app.AppProtoEnums.BROADCAST_TYPE_ORDERED; import static android.app.AppProtoEnums.BROADCAST_TYPE_RESULT_TO; import static android.app.AppProtoEnums.BROADCAST_TYPE_STICKY; import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT; import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__FAILED_STICKY_CANT_HAVE_PERMISSION; import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__FAILED_USER_STOPPED; import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__SUCCESS; import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__UNKNOWN; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Intent; import android.util.IntArray; import com.android.internal.util.FrameworkStatsLog; final class BroadcastSentEventRecord { @NonNull private Intent mIntent; private int mOriginalIntentFlags; private int mSenderUid; private int mRealSenderUid; private boolean mSticky; private boolean mOrdered; private boolean mResultRequested; private int mSenderProcState; private int mSenderUidState; @Nullable private BroadcastRecord mBroadcastRecord; private int mResult; public void setIntent(@NonNull Intent intent) { mIntent = intent; } public void setSenderUid(int uid) { mSenderUid = uid; } public void setRealSenderUid(int uid) { mRealSenderUid = uid; } public void setOriginalIntentFlags(int flags) { mOriginalIntentFlags = flags; } public void setSticky(boolean sticky) { mSticky = sticky; } public void setOrdered(boolean ordered) { mOrdered = ordered; } public void setResultRequested(boolean resultRequested) { mResultRequested = resultRequested; } public void setSenderProcState(int procState) { mSenderProcState = procState; } public void setSenderUidState(int procState) { mSenderUidState = procState; } public void setBroadcastRecord(@NonNull BroadcastRecord record) { mBroadcastRecord = record; } public void setResult(int result) { mResult = result; } public void logToStatsd() { if (Flags.logBroadcastSentEvent()) { int loggingResult = switch (mResult) { case ActivityManager.BROADCAST_SUCCESS -> BROADCAST_SENT__RESULT__SUCCESS; case ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION -> BROADCAST_SENT__RESULT__FAILED_STICKY_CANT_HAVE_PERMISSION; case ActivityManager.BROADCAST_FAILED_USER_STOPPED -> BROADCAST_SENT__RESULT__FAILED_USER_STOPPED; default -> BROADCAST_SENT__RESULT__UNKNOWN; }; int[] types = calculateTypesForLogging(); FrameworkStatsLog.write(BROADCAST_SENT, mIntent.getAction(), mIntent.getFlags(), mOriginalIntentFlags, mSenderUid, mRealSenderUid, mIntent.getPackage() != null, mIntent.getComponent() != null, mBroadcastRecord != null ? mBroadcastRecord.receivers.size() : 0, loggingResult, mBroadcastRecord != null ? mBroadcastRecord.getDeliveryGroupPolicy() : 0, ActivityManager.processStateAmToProto(mSenderProcState), ActivityManager.processStateAmToProto(mSenderUidState), types); } } private int[] calculateTypesForLogging() { if (mBroadcastRecord != null) { return mBroadcastRecord.calculateTypesForLogging(); } else { final IntArray types = new IntArray(); if (mSticky) { types.add(BROADCAST_TYPE_STICKY); } if (mOrdered) { types.add(BROADCAST_TYPE_ORDERED); } if (mResultRequested) { types.add(BROADCAST_TYPE_RESULT_TO); } return types.toArray(); } } }
services/core/java/com/android/server/am/flags.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -184,3 +184,14 @@ flag { description: "Defer submitting binder calls to paused processes." bug: "327038797" } flag { name: "log_broadcast_sent_event" namespace: "backstage_power" description: "Log the broadcast send event to Statsd" bug: "355261986" is_fixed_read_only: true metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file