Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2cdcde5 authored by Sudheer Shanka's avatar Sudheer Shanka Committed by Automerger Merge Worker
Browse files

Merge "Group broadcasts occurred within a certain duration into sessions."...

Merge "Group broadcasts occurred within a certain duration into sessions." into tm-dev am: 0a790c64

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18360308



Change-Id: Id7ea48dd33a65b94d0f611c78c62342fa4d51bc0
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 0363c598 0a790c64
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -246,6 +246,28 @@ public interface AppStandbyInternal {
    @ProcessState
    int getBroadcastResponseFgThresholdState();

    /**
     * Returns the duration within which any broadcasts occurred will be treated as one broadcast
     * session.
     */
    long getBroadcastSessionsDurationMs();

    /**
     * Returns the duration within which any broadcasts occurred (with a corresponding response
     * event) will be treated as one broadcast session. This similar to
     * {@link #getBroadcastSessionsDurationMs()}, except that this duration will be used to group
     * only broadcasts that have a corresponding response event into sessions.
     */
    long getBroadcastSessionsWithResponseDurationMs();

    /**
     * Returns {@code true} if the response event should be attributed to all the broadcast
     * sessions that occurred within the broadcast response window and {@code false} if the
     * response event should be attributed to only the earliest broadcast session within the
     * broadcast response window.
     */
    boolean shouldNoteResponseEventForAllBroadcastSessions();

    /**
     * Return the last known value corresponding to the {@code key} from
     * {@link android.provider.DeviceConfig#NAMESPACE_APP_STANDBY} in AppStandbyController.
+81 −0
Original line number Diff line number Diff line
@@ -376,6 +376,32 @@ public class AppStandbyController
    volatile int mBroadcastResponseFgThresholdState =
            ConstantsObserver.DEFAULT_BROADCAST_RESPONSE_FG_THRESHOLD_STATE;

    /**
     * Duration (in millis) for the window within which any broadcasts occurred will be
     * treated as one broadcast session.
     */
    volatile long mBroadcastSessionsDurationMs =
            ConstantsObserver.DEFAULT_BROADCAST_SESSIONS_DURATION_MS;

    /**
     * Duration (in millis) for the window within which any broadcasts occurred ((with a
     * corresponding response event) will be treated as one broadcast session. This similar to
     * {@link #mBroadcastSessionsDurationMs}, except that this duration will be used to group only
     * broadcasts that have a corresponding response event into sessions.
     */
    volatile long mBroadcastSessionsWithResponseDurationMs =
            ConstantsObserver.DEFAULT_BROADCAST_SESSIONS_WITH_RESPONSE_DURATION_MS;

    /**
     * Denotes whether the response event should be attributed to all broadcast sessions or not.
     * If this is {@code true}, then the response event should be attributed to all the broadcast
     * sessions that occurred within the broadcast response window. Otherwise, the
     * response event should be attributed to only the earliest broadcast session within the
     * broadcast response window.
     */
    volatile boolean mNoteResponseEventForAllBroadcastSessions =
            ConstantsObserver.DEFAULT_NOTE_RESPONSE_EVENT_FOR_ALL_BROADCAST_SESSIONS;

    /**
     * Map of last known values of keys in {@link DeviceConfig#NAMESPACE_APP_STANDBY}.
     *
@@ -1868,6 +1894,21 @@ public class AppStandbyController
        return mBroadcastResponseFgThresholdState;
    }

    @Override
    public long getBroadcastSessionsDurationMs() {
        return mBroadcastSessionsDurationMs;
    }

    @Override
    public long getBroadcastSessionsWithResponseDurationMs() {
        return mBroadcastSessionsWithResponseDurationMs;
    }

    @Override
    public boolean shouldNoteResponseEventForAllBroadcastSessions() {
        return mNoteResponseEventForAllBroadcastSessions;
    }

    @Override
    @Nullable
    public String getAppStandbyConstant(@NonNull String key) {
@@ -2202,6 +2243,18 @@ public class AppStandbyController
        pw.print(ActivityManager.procStateToString(mBroadcastResponseFgThresholdState));
        pw.println();

        pw.print("  mBroadcastSessionsDurationMs=");
        TimeUtils.formatDuration(mBroadcastSessionsDurationMs, pw);
        pw.println();

        pw.print("  mBroadcastSessionsWithResponseDurationMs=");
        TimeUtils.formatDuration(mBroadcastSessionsWithResponseDurationMs, pw);
        pw.println();

        pw.print("  mNoteResponseEventForAllBroadcastSessions=");
        pw.print(mNoteResponseEventForAllBroadcastSessions);
        pw.println();

        pw.println();
        pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
        pw.print(" mAllowRestrictedBucket=");
@@ -2672,6 +2725,13 @@ public class AppStandbyController
                "broadcast_response_window_timeout_ms";
        private static final String KEY_BROADCAST_RESPONSE_FG_THRESHOLD_STATE =
                "broadcast_response_fg_threshold_state";
        private static final String KEY_BROADCAST_SESSIONS_DURATION_MS =
                "broadcast_sessions_duration_ms";
        private static final String KEY_BROADCAST_SESSIONS_WITH_RESPONSE_DURATION_MS =
                "broadcast_sessions_with_response_duration_ms";
        private static final String KEY_NOTE_RESPONSE_EVENT_FOR_ALL_BROADCAST_SESSIONS =
                "note_response_event_for_all_broadcast_sessions";

        public static final long DEFAULT_CHECK_IDLE_INTERVAL_MS =
                COMPRESS_TIME ? ONE_MINUTE : 4 * ONE_HOUR;
        public static final long DEFAULT_STRONG_USAGE_TIMEOUT =
@@ -2705,6 +2765,12 @@ public class AppStandbyController
                2 * ONE_MINUTE;
        public static final int DEFAULT_BROADCAST_RESPONSE_FG_THRESHOLD_STATE =
                ActivityManager.PROCESS_STATE_TOP;
        public static final long DEFAULT_BROADCAST_SESSIONS_DURATION_MS =
                2 * ONE_MINUTE;
        public static final long DEFAULT_BROADCAST_SESSIONS_WITH_RESPONSE_DURATION_MS =
                2 * ONE_MINUTE;
        public static final boolean DEFAULT_NOTE_RESPONSE_EVENT_FOR_ALL_BROADCAST_SESSIONS =
                true;

        ConstantsObserver(Handler handler) {
            super(handler);
@@ -2832,6 +2898,21 @@ public class AppStandbyController
                                    KEY_BROADCAST_RESPONSE_FG_THRESHOLD_STATE,
                                    DEFAULT_BROADCAST_RESPONSE_FG_THRESHOLD_STATE);
                            break;
                        case KEY_BROADCAST_SESSIONS_DURATION_MS:
                            mBroadcastSessionsDurationMs = properties.getLong(
                                    KEY_BROADCAST_SESSIONS_DURATION_MS,
                                    DEFAULT_BROADCAST_SESSIONS_DURATION_MS);
                            break;
                        case KEY_BROADCAST_SESSIONS_WITH_RESPONSE_DURATION_MS:
                            mBroadcastSessionsWithResponseDurationMs = properties.getLong(
                                    KEY_BROADCAST_SESSIONS_WITH_RESPONSE_DURATION_MS,
                                    DEFAULT_BROADCAST_SESSIONS_WITH_RESPONSE_DURATION_MS);
                            break;
                        case KEY_NOTE_RESPONSE_EVENT_FOR_ALL_BROADCAST_SESSIONS:
                            mNoteResponseEventForAllBroadcastSessions = properties.getBoolean(
                                    KEY_NOTE_RESPONSE_EVENT_FOR_ALL_BROADCAST_SESSIONS,
                                    DEFAULT_NOTE_RESPONSE_EVENT_FOR_ALL_BROADCAST_SESSIONS);
                            break;
                        default:
                            if (!timeThresholdsUpdated
                                    && (name.startsWith(KEY_PREFIX_SCREEN_TIME_THRESHOLD)
+11 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.usage;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.util.LongArrayQueue;

import java.util.Objects;

@@ -30,6 +31,7 @@ class BroadcastEvent {
    private String mTargetPackage;
    private int mTargetUserId;
    private long mIdForResponseEvent;
    private final LongArrayQueue mTimestampsMs;

    BroadcastEvent(int sourceUid, @NonNull String targetPackage, @UserIdInt int targetUserId,
            long idForResponseEvent) {
@@ -37,6 +39,7 @@ class BroadcastEvent {
        mTargetPackage = targetPackage;
        mTargetUserId = targetUserId;
        mIdForResponseEvent = idForResponseEvent;
        mTimestampsMs = new LongArrayQueue();
    }

    public int getSourceUid() {
@@ -55,6 +58,14 @@ class BroadcastEvent {
        return mIdForResponseEvent;
    }

    public LongArrayQueue getTimestampsMs() {
        return mTimestampsMs;
    }

    public void addTimestampMs(long timestampMs) {
        mTimestampsMs.addLast(timestampMs);
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (this == obj) {
+97 −48
Original line number Diff line number Diff line
@@ -24,8 +24,10 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager.ProcessState;
import android.app.usage.BroadcastResponseStats;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.LongSparseArray;
import android.util.ArraySet;
import android.util.LongArrayQueue;
import android.util.Slog;
import android.util.SparseArray;

@@ -89,14 +91,14 @@ class BroadcastResponseStatsTracker {
            return;
        }
        synchronized (mLock) {
            final LongSparseArray<BroadcastEvent> broadcastEvents =
            final ArraySet<BroadcastEvent> broadcastEvents =
                    getOrCreateBroadcastEventsLocked(targetPackage, targetUser);
            final BroadcastEvent broadcastEvent = new BroadcastEvent(
            final BroadcastEvent broadcastEvent = getOrCreateBroadcastEvent(broadcastEvents,
                    sourceUid, targetPackage, targetUser.getIdentifier(), idForResponseEvent);
            broadcastEvents.append(timestampMs, broadcastEvent);
            final BroadcastResponseStats responseStats =
                    getOrCreateBroadcastResponseStats(broadcastEvent);
            responseStats.incrementBroadcastsDispatchedCount(1);
            broadcastEvent.addTimestampMs(timestampMs);

            // Delete any old broadcast event related data so that we don't keep accumulating them.
            recordAndPruneOldBroadcastDispatchTimestamps(broadcastEvent);
        }
    }

@@ -120,28 +122,45 @@ class BroadcastResponseStatsTracker {
            @NonNull String packageName, UserHandle user, @ElapsedRealtimeLong long timestampMs) {
        mLogger.logNotificationEvent(event, packageName, user, timestampMs);
        synchronized (mLock) {
            final LongSparseArray<BroadcastEvent> broadcastEvents =
            final ArraySet<BroadcastEvent> broadcastEvents =
                    getBroadcastEventsLocked(packageName, user);
            if (broadcastEvents == null) {
                return;
            }
            // TODO (206518114): Add LongSparseArray.removeAtRange()
            final long broadcastResponseWindowDurationMs =
                    mAppStandby.getBroadcastResponseWindowDurationMs();
            final long broadcastsSessionWithResponseDurationMs =
                    mAppStandby.getBroadcastSessionsWithResponseDurationMs();
            final boolean recordAllBroadcastsSessionsWithinResponseWindow =
                    mAppStandby.shouldNoteResponseEventForAllBroadcastSessions();
            for (int i = broadcastEvents.size() - 1; i >= 0; --i) {
                final long dispatchTimestampMs = broadcastEvents.keyAt(i);
                final BroadcastEvent broadcastEvent = broadcastEvents.valueAt(i);
                recordAndPruneOldBroadcastDispatchTimestamps(broadcastEvent);

                final LongArrayQueue dispatchTimestampsMs = broadcastEvent.getTimestampsMs();
                long broadcastsSessionEndTimestampMs = 0;
                // We only need to look at the broadcast events that occurred before
                // this notification related event.
                while (dispatchTimestampsMs.size() > 0
                        && dispatchTimestampsMs.peekFirst() < timestampMs) {
                    final long dispatchTimestampMs = dispatchTimestampsMs.peekFirst();
                    final long elapsedDurationMs = timestampMs - dispatchTimestampMs;
                if (elapsedDurationMs <= 0) {
                    continue;
                }
                if (dispatchTimestampMs >= timestampMs) {
                    continue;
                    // Only increment the counts if the broadcast was sent not too long ago, as
                    // decided by 'broadcastResponseWindowDurationMs' and is part of a new session.
                    // That is, it occurred 'broadcastsSessionWithResponseDurationMs' after the
                    // previously handled broadcast event which is represented by
                    // 'broadcastsSessionEndTimestampMs'.
                    if (elapsedDurationMs <= broadcastResponseWindowDurationMs
                            && dispatchTimestampMs >= broadcastsSessionEndTimestampMs) {
                        if (broadcastsSessionEndTimestampMs != 0
                                && !recordAllBroadcastsSessionsWithinResponseWindow) {
                            break;
                        }
                if (elapsedDurationMs <= mAppStandby.getBroadcastResponseWindowDurationMs()) {
                    final BroadcastEvent broadcastEvent = broadcastEvents.valueAt(i);
                        final BroadcastResponseStats responseStats =
                            getBroadcastResponseStats(broadcastEvent);
                    if (responseStats == null) {
                        continue;
                    }
                                getOrCreateBroadcastResponseStats(broadcastEvent);
                        responseStats.incrementBroadcastsDispatchedCount(1);
                        broadcastsSessionEndTimestampMs = dispatchTimestampMs
                                + broadcastsSessionWithResponseDurationMs;
                        switch (event) {
                            case NOTIFICATION_EVENT_TYPE_POSTED:
                                responseStats.incrementNotificationsPostedCount(1);
@@ -156,10 +175,36 @@ class BroadcastResponseStatsTracker {
                                Slog.wtf(TAG, "Unknown event: " + event);
                        }
                    }
                    dispatchTimestampsMs.removeFirst();
                }
                if (dispatchTimestampsMs.size() == 0) {
                    broadcastEvents.removeAt(i);
                }
            }
        }
    }

    @GuardedBy("mLock")
    private void recordAndPruneOldBroadcastDispatchTimestamps(BroadcastEvent broadcastEvent) {
        final LongArrayQueue timestampsMs = broadcastEvent.getTimestampsMs();
        final long broadcastResponseWindowDurationMs =
                mAppStandby.getBroadcastResponseWindowDurationMs();
        final long broadcastsSessionDurationMs =
                mAppStandby.getBroadcastSessionsDurationMs();
        final long nowElapsedMs = SystemClock.elapsedRealtime();
        long broadcastsSessionEndTimestampMs = 0;
        while (timestampsMs.size() > 0
                && timestampsMs.peekFirst() < (nowElapsedMs - broadcastResponseWindowDurationMs)) {
            final long eventTimestampMs = timestampsMs.peekFirst();
            if (eventTimestampMs >= broadcastsSessionEndTimestampMs) {
                final BroadcastResponseStats responseStats =
                        getOrCreateBroadcastResponseStats(broadcastEvent);
                responseStats.incrementBroadcastsDispatchedCount(1);
                broadcastsSessionEndTimestampMs = eventTimestampMs + broadcastsSessionDurationMs;
            }
            timestampsMs.removeFirst();
        }
    }

    @NonNull List<BroadcastResponseStats> queryBroadcastResponseStats(int callingUid,
            @Nullable String packageName, @IntRange(from = 0) long id, @UserIdInt int userId) {
@@ -247,7 +292,7 @@ class BroadcastResponseStatsTracker {

    @GuardedBy("mLock")
    @Nullable
    private LongSparseArray<BroadcastEvent> getBroadcastEventsLocked(
    private ArraySet<BroadcastEvent> getBroadcastEventsLocked(
            @NonNull String packageName, UserHandle user) {
        final UserBroadcastEvents userBroadcastEvents = mUserBroadcastEvents.get(
                user.getIdentifier());
@@ -259,7 +304,7 @@ class BroadcastResponseStatsTracker {

    @GuardedBy("mLock")
    @NonNull
    private LongSparseArray<BroadcastEvent> getOrCreateBroadcastEventsLocked(
    private ArraySet<BroadcastEvent> getOrCreateBroadcastEventsLocked(
            @NonNull String packageName, UserHandle user) {
        UserBroadcastEvents userBroadcastEvents = mUserBroadcastEvents.get(user.getIdentifier());
        if (userBroadcastEvents == null) {
@@ -269,16 +314,6 @@ class BroadcastResponseStatsTracker {
        return userBroadcastEvents.getOrCreateBroadcastEvents(packageName);
    }

    @GuardedBy("mLock")
    @Nullable
    private BroadcastResponseStats getBroadcastResponseStats(
            @NonNull BroadcastEvent broadcastEvent) {
        final int sourceUid = broadcastEvent.getSourceUid();
        final SparseArray<UserBroadcastResponseStats> responseStatsForUid =
                mUserResponseStats.get(sourceUid);
        return getBroadcastResponseStats(responseStatsForUid, broadcastEvent);
    }

    @GuardedBy("mLock")
    @Nullable
    private BroadcastResponseStats getBroadcastResponseStats(
@@ -315,6 +350,20 @@ class BroadcastResponseStatsTracker {
        return userResponseStats.getOrCreateBroadcastResponseStats(broadcastEvent);
    }

    private static BroadcastEvent getOrCreateBroadcastEvent(
            ArraySet<BroadcastEvent> broadcastEvents,
            int sourceUid, String targetPackage, int targetUserId, long idForResponseEvent) {
        final BroadcastEvent broadcastEvent = new BroadcastEvent(
                sourceUid, targetPackage, targetUserId, idForResponseEvent);
        final int index = broadcastEvents.indexOf(broadcastEvent);
        if (index >= 0) {
            return broadcastEvents.valueAt(index);
        } else {
            broadcastEvents.add(broadcastEvent);
            return broadcastEvent;
        }
    }

    void dump(@NonNull IndentingPrintWriter ipw) {
        ipw.println("Broadcast response stats:");
        ipw.increaseIndent();
+20 −11
Original line number Diff line number Diff line
@@ -19,7 +19,8 @@ package com.android.server.usage;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.ArrayMap;
import android.util.LongSparseArray;
import android.util.ArraySet;
import android.util.LongArrayQueue;
import android.util.TimeUtils;

import com.android.internal.util.IndentingPrintWriter;
@@ -30,17 +31,17 @@ class UserBroadcastEvents {
     * Here targetPackage refers to the package receiving the broadcast and BroadcastEvent objects
     * corresponding to each broadcast it is receiving.
     */
    private ArrayMap<String, LongSparseArray<BroadcastEvent>> mBroadcastEvents = new ArrayMap();
    private ArrayMap<String, ArraySet<BroadcastEvent>> mBroadcastEvents = new ArrayMap();

    @Nullable LongSparseArray<BroadcastEvent> getBroadcastEvents(@NonNull String packageName) {
    @Nullable ArraySet<BroadcastEvent> getBroadcastEvents(@NonNull String packageName) {
        return mBroadcastEvents.get(packageName);
    }

    @NonNull LongSparseArray<BroadcastEvent> getOrCreateBroadcastEvents(
    @NonNull ArraySet<BroadcastEvent> getOrCreateBroadcastEvents(
            @NonNull String packageName) {
        LongSparseArray<BroadcastEvent> broadcastEvents = mBroadcastEvents.get(packageName);
        ArraySet<BroadcastEvent> broadcastEvents = mBroadcastEvents.get(packageName);
        if (broadcastEvents == null) {
            broadcastEvents = new LongSparseArray<>();
            broadcastEvents = new ArraySet<>();
            mBroadcastEvents.put(packageName, broadcastEvents);
        }
        return broadcastEvents;
@@ -56,7 +57,7 @@ class UserBroadcastEvents {

    void clear(int uid) {
        for (int i = mBroadcastEvents.size() - 1; i >= 0; --i) {
            final LongSparseArray<BroadcastEvent> broadcastEvents = mBroadcastEvents.valueAt(i);
            final ArraySet<BroadcastEvent> broadcastEvents = mBroadcastEvents.valueAt(i);
            for (int j = broadcastEvents.size() - 1; j >= 0; --j) {
                if (broadcastEvents.valueAt(j).getSourceUid() == uid) {
                    broadcastEvents.removeAt(j);
@@ -68,18 +69,26 @@ class UserBroadcastEvents {
    void dump(@NonNull IndentingPrintWriter ipw) {
        for (int i = 0; i < mBroadcastEvents.size(); ++i) {
            final String packageName = mBroadcastEvents.keyAt(i);
            final LongSparseArray<BroadcastEvent> broadcastEvents = mBroadcastEvents.valueAt(i);
            final ArraySet<BroadcastEvent> broadcastEvents = mBroadcastEvents.valueAt(i);
            ipw.println(packageName + ":");
            ipw.increaseIndent();
            if (broadcastEvents.size() == 0) {
                ipw.println("<empty>");
            } else {
                for (int j = 0; j < broadcastEvents.size(); ++j) {
                    final long timestampMs = broadcastEvents.keyAt(j);
                    final BroadcastEvent broadcastEvent = broadcastEvents.valueAt(j);
                    TimeUtils.formatDuration(timestampMs, ipw);
                    ipw.print(": ");
                    ipw.println(broadcastEvent);
                    ipw.increaseIndent();
                    final LongArrayQueue timestampsMs = broadcastEvent.getTimestampsMs();
                    for (int timestampIdx = 0; timestampIdx < timestampsMs.size(); ++timestampIdx) {
                        if (timestampIdx > 0) {
                            ipw.print(',');
                        }
                        final long timestampMs = timestampsMs.get(timestampIdx);
                        TimeUtils.formatDuration(timestampMs, ipw);
                    }
                    ipw.println();
                    ipw.decreaseIndent();
                }
            }
            ipw.decreaseIndent();