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

Commit 30ff3156 authored by Jonathan Backer's avatar Jonathan Backer
Browse files

Remove dead code

FrameworkWakelockInfo will not launch. It was used to cross validate
move_wsc_logging_to_notifier.

Bug: 352602149
Flag: EXEMPT delete dead code
Test: atest PowerStatsTestsRavenwood
Test: atest PowerStatsTests
Change-Id: I0c01602db35b60f557df9b5b02bbb8e60eed49f0
parent 70cc5d66
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -52,9 +52,6 @@ public class PowerManagerFlags {
            Flags::perDisplayWakeByTouch
    );

    private final FlagState mFrameworkWakelockInfo =
            new FlagState(Flags.FLAG_FRAMEWORK_WAKELOCK_INFO, Flags::frameworkWakelockInfo);

    private final FlagState mPolicyReasonInDisplayPowerRequest = new FlagState(
            Flags.FLAG_POLICY_REASON_IN_DISPLAY_POWER_REQUEST,
            Flags::policyReasonInDisplayPowerRequest
@@ -95,13 +92,6 @@ public class PowerManagerFlags {
        return mPerDisplayWakeByTouch.isEnabled();
    }

    /**
     * @return Whether FrameworkWakelockInfo atom logging is enabled or not.
     */
    public boolean isFrameworkWakelockInfoEnabled() {
        return mFrameworkWakelockInfo.isEnabled();
    }

    /**
     * @return Whether the wakefulness reason is populated in DisplayPowerRequest.
     */
@@ -140,7 +130,6 @@ public class PowerManagerFlags {
        pw.println(" " + mEarlyScreenTimeoutDetectorFlagState);
        pw.println(" " + mImproveWakelockLatency);
        pw.println(" " + mPerDisplayWakeByTouch);
        pw.println(" " + mFrameworkWakelockInfo);
        pw.println(" " + mMoveWscLoggingToNotifier);
        pw.println(" " + mWakelockAttributionViaWorkchain);
        pw.println(" " + mDisableFrozenProcessWakelocks);
+0 −7
Original line number Diff line number Diff line
@@ -49,13 +49,6 @@ flag {
    is_fixed_read_only: true
}

flag {
    name: "framework_wakelock_info"
    namespace: "power"
    description: "Feature flag to enable statsd pulling of FrameworkWakelockInfo atoms"
    bug: "380847722"
}

flag {
    name: "policy_reason_in_display_power_request"
    namespace: "wear_frameworks"
+0 −16
Original line number Diff line number Diff line
@@ -144,7 +144,6 @@ import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.server.LocalServices;
import com.android.server.power.feature.PowerManagerFlags;
import com.android.server.power.optimization.Flags;
import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
@@ -5063,10 +5062,6 @@ public class BatteryStatsImpl extends BatteryStats {
                        uidStats.mProcessState, true /* acquired */,
                        getPowerManagerWakeLockLevel(type));
            }
            if (mPowerManagerFlags.isFrameworkWakelockInfoEnabled()) {
                mFrameworkEvents.noteStartWakeLock(
                        mapIsolatedUid(uid), name, getPowerManagerWakeLockLevel(type), uptimeMs);
            }
        }
    }
@@ -5114,10 +5109,6 @@ public class BatteryStatsImpl extends BatteryStats {
                        uidStats.mProcessState, false/* acquired */,
                        getPowerManagerWakeLockLevel(type));
            }
            if (mPowerManagerFlags.isFrameworkWakelockInfoEnabled()) {
                mFrameworkEvents.noteStopWakeLock(
                        mapIsolatedUid(uid), name, getPowerManagerWakeLockLevel(type), uptimeMs);
            }
            if (mappedUid != uid) {
                // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
@@ -11274,9 +11265,6 @@ public class BatteryStatsImpl extends BatteryStats {
        return mTmpCpuTimeInFreq;
    }
    WakelockStatsFrameworkEvents mFrameworkEvents = new WakelockStatsFrameworkEvents();
    PowerManagerFlags mPowerManagerFlags = new PowerManagerFlags();
    public BatteryStatsImpl(@NonNull BatteryStatsConfig config, @NonNull Clock clock,
            @NonNull MonotonicClock monotonicClock, @Nullable File systemDir,
            @NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback,
@@ -15895,10 +15883,6 @@ public class BatteryStatsImpl extends BatteryStats {
                // Already plugged in. Schedule the long plug in alarm.
                scheduleNextResetWhilePluggedInCheck();
            }
            if (mPowerManagerFlags.isFrameworkWakelockInfoEnabled()) {
                mFrameworkEvents.initialize(context);
            }
        }
    }
+0 −335
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.power.stats;

import android.app.StatsManager;
import android.content.Context;
import android.os.SystemClock;
import android.util.Log;
import android.util.StatsEvent;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.FrameworkStatsLog;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/** A class to initialise and log metrics pulled by statsd. */
public class WakelockStatsFrameworkEvents {
    // statsd has a dimensional limit on the number of different keys it can handle.
    // Beyond that limit, statsd will drop data.
    //
    // When we have seem SUMMARY_THRESHOLD distinct (uid, tag, wakeLockLevel) keys,
    // we start summarizing new keys as (uid, OVERFLOW_TAG, OVERFLOW_LEVEL) to
    // reduce the number of keys we pass to statsd.
    //
    // When we reach MAX_WAKELOCK_DIMENSIONS distinct keys, we summarize all new keys
    // as (OVERFLOW_UID, HARD_CAP_TAG, OVERFLOW_LEVEL) to hard cap the number of
    // distinct keys we pass to statsd.
    @VisibleForTesting public static final int SUMMARY_THRESHOLD = 500;
    @VisibleForTesting public static final int MAX_WAKELOCK_DIMENSIONS = 1000;

    @VisibleForTesting public static final int HARD_CAP_UID = -1;
    @VisibleForTesting public static final String OVERFLOW_TAG = "*overflow*";
    @VisibleForTesting public static final String HARD_CAP_TAG = "*overflow hard cap*";
    @VisibleForTesting public static final int OVERFLOW_LEVEL = 1;

    private static class WakeLockKey {
        private int uid;
        private String tag;
        private int powerManagerWakeLockLevel;
        private int hashCode;

        WakeLockKey(int uid, String tag, int powerManagerWakeLockLevel) {
            this.uid = uid;
            this.tag = new String(tag);
            this.powerManagerWakeLockLevel = powerManagerWakeLockLevel;

            this.hashCode = Objects.hash(uid, tag, powerManagerWakeLockLevel);
        }

        int getUid() {
            return uid;
        }

        String getTag() {
            return tag;
        }

        int getPowerManagerWakeLockLevel() {
            return powerManagerWakeLockLevel;
        }

        void setOverflow() {
            tag = OVERFLOW_TAG;
            powerManagerWakeLockLevel = OVERFLOW_LEVEL;
            this.hashCode = Objects.hash(uid, tag, powerManagerWakeLockLevel);
        }

        void setHardCap() {
            uid = HARD_CAP_UID;
            tag = HARD_CAP_TAG;
            powerManagerWakeLockLevel = OVERFLOW_LEVEL;
            this.hashCode = Objects.hash(uid, tag, powerManagerWakeLockLevel);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || !(o instanceof WakeLockKey)) return false;

            WakeLockKey that = (WakeLockKey) o;
            return uid == that.uid
                    && tag.equals(that.tag)
                    && powerManagerWakeLockLevel == that.powerManagerWakeLockLevel;
        }

        @Override
        public int hashCode() {
            return this.hashCode;
        }
    }

    private static class WakeLockStats {
        // accumulated uptime attributed to this WakeLock since boot, where overlap
        // (including nesting) is ignored
        public long uptimeMillis = 0;

        // count of WakeLocks that have been acquired and then released
        public long completedCount = 0;
    }

    private final Object mLock = new Object();

    @GuardedBy("mLock")
    private final Map<WakeLockKey, WakeLockStats> mWakeLockStats = new HashMap<>();

    private static class WakeLockData {
        // uptime millis when first acquired
        public long acquireUptimeMillis = 0;
        public int refCount = 0;

        WakeLockData(long uptimeMillis) {
            acquireUptimeMillis = uptimeMillis;
        }
    }

    @GuardedBy("mLock")
    private final Map<WakeLockKey, WakeLockData> mOpenWakeLocks = new HashMap<>();

    public void noteStartWakeLock(
            int uid, String tag, int powerManagerWakeLockLevel, long eventUptimeMillis) {
        final WakeLockKey key = new WakeLockKey(uid, tag, powerManagerWakeLockLevel);

        synchronized (mLock) {
            WakeLockData data =
                    mOpenWakeLocks.computeIfAbsent(key, k -> new WakeLockData(eventUptimeMillis));
            data.refCount++;
            mOpenWakeLocks.put(key, data);
        }
    }

    @VisibleForTesting
    @GuardedBy("mLock")
    public boolean inOverflow() {
        return mWakeLockStats.size() >= SUMMARY_THRESHOLD;
    }

    @VisibleForTesting
    @GuardedBy("mLock")
    public boolean inHardCap() {
        return mWakeLockStats.size() >= MAX_WAKELOCK_DIMENSIONS;
    }

    public void noteStopWakeLock(
            int uid, String tag, int powerManagerWakeLockLevel, long eventUptimeMillis) {
        WakeLockKey key = new WakeLockKey(uid, tag, powerManagerWakeLockLevel);

        synchronized (mLock) {
            WakeLockData data = mOpenWakeLocks.get(key);
            if (data == null) {
                Log.e(TAG, "WakeLock not found when stopping: " + uid + " " + tag);
                return;
            }

            if (data.refCount == 1) {
                mOpenWakeLocks.remove(key);
                long wakeLockDur = eventUptimeMillis - data.acquireUptimeMillis;

                // Rewrite key if in an overflow state.
                if (inOverflow() && !mWakeLockStats.containsKey(key)) {
                    key.setOverflow();
                    if (inHardCap() && !mWakeLockStats.containsKey(key)) {
                        key.setHardCap();
                    }
                }

                WakeLockStats stats = mWakeLockStats.computeIfAbsent(key, k -> new WakeLockStats());
                stats.uptimeMillis += wakeLockDur;
                stats.completedCount++;
                mWakeLockStats.put(key, stats);
            } else {
                data.refCount--;
                mOpenWakeLocks.put(key, data);
            }
        }
    }

    // Shim interface for testing.
    @VisibleForTesting
    public interface EventLogger {
        void logResult(
                int uid, String tag, int wakeLockLevel, long uptimeMillis, long completedCount);
    }

    public List<StatsEvent> pullFrameworkWakelockInfoAtoms() {
        List<StatsEvent> result = new ArrayList<>();
        EventLogger logger =
                new EventLogger() {
                    public void logResult(
                            int uid,
                            String tag,
                            int wakeLockLevel,
                            long uptimeMillis,
                            long completedCount) {
                        StatsEvent event =
                                StatsEvent.newBuilder()
                                        .setAtomId(FrameworkStatsLog.FRAMEWORK_WAKELOCK_INFO)
                                        .writeInt(uid)
                                        .writeString(tag)
                                        .writeInt(wakeLockLevel)
                                        .writeLong(uptimeMillis)
                                        .writeLong(completedCount)
                                        .build();
                        result.add(event);
                    }
                };
        pullFrameworkWakelockInfoAtoms(SystemClock.uptimeMillis(), logger);
        return result;
    }

    @VisibleForTesting
    public void pullFrameworkWakelockInfoAtoms(long nowMillis, EventLogger logger) {
        HashSet<WakeLockKey> keys = new HashSet<>();

        // Used to collect open WakeLocks when in an overflow state.
        HashMap<WakeLockKey, WakeLockStats> openOverflowStats = new HashMap<>();

        synchronized (mLock) {
            keys.addAll(mWakeLockStats.keySet());

            // If we are in an overflow state, an open wakelock may have a new key
            // that needs to be summarized.
            if (inOverflow()) {
                for (WakeLockKey key : mOpenWakeLocks.keySet()) {
                    if (!mWakeLockStats.containsKey(key)) {
                        WakeLockData data = mOpenWakeLocks.get(key);

                        key.setOverflow();
                        if (inHardCap() && !mWakeLockStats.containsKey(key)) {
                            key.setHardCap();
                        }
                        keys.add(key);

                        WakeLockStats stats =
                                openOverflowStats.computeIfAbsent(key, k -> new WakeLockStats());
                        stats.uptimeMillis += nowMillis - data.acquireUptimeMillis;
                        openOverflowStats.put(key, stats);
                    }
                }
            } else {
                keys.addAll(mOpenWakeLocks.keySet());
            }

            for (WakeLockKey key : keys) {
                long openWakeLockUptime = 0;
                WakeLockData data = mOpenWakeLocks.get(key);
                if (data != null) {
                    openWakeLockUptime = nowMillis - data.acquireUptimeMillis;
                }

                WakeLockStats stats = mWakeLockStats.computeIfAbsent(key, k -> new WakeLockStats());
                WakeLockStats extraTime =
                        openOverflowStats.computeIfAbsent(key, k -> new WakeLockStats());

                long totalUpdate = openWakeLockUptime + stats.uptimeMillis + extraTime.uptimeMillis;
                long totalCount = stats.completedCount + extraTime.completedCount;
                logger.logResult(key.getUid(), key.getTag(), key.getPowerManagerWakeLockLevel(),
                        totalUpdate, totalCount);
            }
        }
    }

    private static final String TAG = "BatteryStatsPulledMetrics";

    private final StatsPullCallbackHandler mStatsPullCallbackHandler =
            new StatsPullCallbackHandler();

    private boolean mIsInitialized = false;

    public void initialize(Context context) {
        if (mIsInitialized) {
            return;
        }

        final StatsManager statsManager = context.getSystemService(StatsManager.class);
        if (statsManager == null) {
            Log.e(
                    TAG,
                    "Error retrieving StatsManager. Cannot initialize BatteryStatsPulledMetrics.");
        } else {
            Log.d(TAG, "Registering callback with StatsManager");

            // DIRECT_EXECUTOR means that callback will run on binder thread.
            statsManager.setPullAtomCallback(
                    FrameworkStatsLog.FRAMEWORK_WAKELOCK_INFO,
                    null /* metadata */,
                    ConcurrentUtils.DIRECT_EXECUTOR,
                    mStatsPullCallbackHandler);
            mIsInitialized = true;
        }
    }

    private class StatsPullCallbackHandler implements StatsManager.StatsPullAtomCallback {
        @Override
        public int onPullAtom(int atomTag, List<StatsEvent> data) {
            // handle the tags appropriately.
            List<StatsEvent> events = pullEvents(atomTag);
            if (events == null) {
                return StatsManager.PULL_SKIP;
            }

            data.addAll(events);
            return StatsManager.PULL_SUCCESS;
        }

        private List<StatsEvent> pullEvents(int atomTag) {
            switch (atomTag) {
                case FrameworkStatsLog.FRAMEWORK_WAKELOCK_INFO:
                    return pullFrameworkWakelockInfoAtoms();
                default:
                    return null;
            }
        }
    }
}
+1 −12
Original line number Diff line number Diff line
@@ -54,8 +54,6 @@ import android.os.HandlerThread;
import android.os.Parcel;
import android.os.WakeLockStats;
import android.os.WorkSource;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.platform.test.ravenwood.RavenwoodRule;
import android.util.SparseArray;
import android.view.Display;
@@ -69,7 +67,6 @@ import com.android.internal.os.KernelSingleUidTimeReader;
import com.android.internal.os.LongArrayMultiStateCounter;
import com.android.internal.os.MonotonicClock;
import com.android.internal.os.PowerProfile;
import com.android.server.power.feature.flags.Flags;

import com.google.common.collect.ImmutableList;
import com.google.common.truth.LongSubject;
@@ -90,14 +87,7 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
@SuppressWarnings("GuardedBy")
public class BatteryStatsImplTest {
    @Rule(order = 0)
    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
            .setSystemPropertyImmutable("persist.sys.com.android.server.power.feature.flags."
                + "framework_wakelock_info-override", null)
            .build();

    @Rule(order = 1)
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
    @Rule public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder().build();

    @Mock
    private KernelCpuUidFreqTimeReader mKernelUidCpuFreqTimeReader;
@@ -570,7 +560,6 @@ public class BatteryStatsImplTest {
    }

    @Test
    @EnableFlags(Flags.FLAG_FRAMEWORK_WAKELOCK_INFO)
    public void testGetWakeLockStats() {
        mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);

Loading