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

Commit a7502ea9 authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Send only the latest battery change events.

Bug: 361334584
Test: manual
Flag: com.android.server.flags.consolidate_battery_change_events
Change-Id: I25f0768fda0050b9066cbd9a7f57dea5c6205905
parent 42fa58b8
Loading
Loading
Loading
Loading
+135 −34
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import static com.android.server.health.Utils.copyV1Battery;

import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
@@ -67,6 +68,7 @@ import android.util.proto.ProtoOutputStream;

import com.android.internal.app.IBatteryStats;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.DumpUtils;
import com.android.server.am.BatteryStatsService;
import com.android.server.health.HealthServiceWrapper;
@@ -207,18 +209,18 @@ public final class BatteryService extends SystemService {
    private final CopyOnWriteArraySet<BatteryManagerInternal.ChargingPolicyChangeListener>
            mChargingPolicyChangeListeners = new CopyOnWriteArraySet<>();

    private Bundle mBatteryChangedOptions = BroadcastOptions.makeBasic()
    private static final Bundle BATTERY_CHANGED_OPTIONS = BroadcastOptions.makeBasic()
            .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
            .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
            .toBundle();
    /** Used for both connected/disconnected, so match using key */
    private Bundle mPowerOptions = BroadcastOptions.makeBasic()
    private static final Bundle POWER_OPTIONS = BroadcastOptions.makeBasic()
            .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
            .setDeliveryGroupMatchingKey("android", Intent.ACTION_POWER_CONNECTED)
            .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
            .toBundle();
    /** Used for both low/okay, so match using key */
    private Bundle mBatteryOptions = BroadcastOptions.makeBasic()
    private static final Bundle BATTERY_OPTIONS = BroadcastOptions.makeBasic()
            .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
            .setDeliveryGroupMatchingKey("android", Intent.ACTION_BATTERY_OKAY)
            .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
@@ -226,11 +228,60 @@ public final class BatteryService extends SystemService {

    private MetricsLogger mMetricsLogger;

    private static final int MSG_BROADCAST_BATTERY_CHANGED = 1;
    private static final int MSG_BROADCAST_POWER_CONNECTION_CHANGED = 2;
    private static final int MSG_BROADCAST_BATTERY_LOW_OKAY = 3;

    private final Handler.Callback mLocalCallback = msg -> {
        switch (msg.what) {
            case MSG_BROADCAST_BATTERY_CHANGED: {
                final SomeArgs args = (SomeArgs) msg.obj;
                final Context context;
                final Intent intent;
                try {
                    context = (Context) args.arg1;
                    intent = (Intent) args.arg2;
                } finally {
                    args.recycle();
                }
                broadcastBatteryChangedIntent(context, intent, BATTERY_CHANGED_OPTIONS);
                return true;
            }
            case MSG_BROADCAST_POWER_CONNECTION_CHANGED: {
                final SomeArgs args = (SomeArgs) msg.obj;
                final Context context;
                final Intent intent;
                try {
                    context = (Context) args.arg1;
                    intent = (Intent) args.arg2;
                } finally {
                    args.recycle();
                }
                sendBroadcastToAllUsers(context, intent, POWER_OPTIONS);
                return true;
            }
            case MSG_BROADCAST_BATTERY_LOW_OKAY: {
                final SomeArgs args = (SomeArgs) msg.obj;
                final Context context;
                final Intent intent;
                try {
                    context = (Context) args.arg1;
                    intent = (Intent) args.arg2;
                } finally {
                    args.recycle();
                }
                sendBroadcastToAllUsers(context, intent, BATTERY_OPTIONS);
                return true;
            }
        }
        return false;
    };

    public BatteryService(Context context) {
        super(context);

        mContext = context;
        mHandler = new Handler(true /*async*/);
        mHandler = new Handler(mLocalCallback, true /*async*/);
        mLed = new Led(context, getLocalService(LightsManager.class));
        mBatteryStats = BatteryStatsService.getService();
        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
@@ -660,53 +711,89 @@ public final class BatteryService extends SystemService {
                final Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                if (com.android.server.flags.Flags.consolidateBatteryChangeEvents()) {
                    mHandler.removeMessages(MSG_BROADCAST_POWER_CONNECTION_CHANGED);
                    final SomeArgs args = SomeArgs.obtain();
                    args.arg1 = mContext;
                    args.arg2 = statusIntent;
                    mHandler.obtainMessage(MSG_BROADCAST_POWER_CONNECTION_CHANGED, args)
                            .sendToTarget();
                } else {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
                                mPowerOptions);
                                    POWER_OPTIONS);
                        }
                    });
                }
            }
            else if (mPlugType == 0 && mLastPlugType != 0) {
                final Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                if (com.android.server.flags.Flags.consolidateBatteryChangeEvents()) {
                    mHandler.removeMessages(MSG_BROADCAST_POWER_CONNECTION_CHANGED);
                    final SomeArgs args = SomeArgs.obtain();
                    args.arg1 = mContext;
                    args.arg2 = statusIntent;
                    mHandler.obtainMessage(MSG_BROADCAST_POWER_CONNECTION_CHANGED, args)
                            .sendToTarget();
                } else {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
                                mPowerOptions);
                                    POWER_OPTIONS);
                        }
                    });
                }
            }

            if (shouldSendBatteryLowLocked()) {
                mSentLowBatteryBroadcast = true;
                final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                if (com.android.server.flags.Flags.consolidateBatteryChangeEvents()) {
                    mHandler.removeMessages(MSG_BROADCAST_BATTERY_LOW_OKAY);
                    final SomeArgs args = SomeArgs.obtain();
                    args.arg1 = mContext;
                    args.arg2 = statusIntent;
                    mHandler.obtainMessage(MSG_BROADCAST_BATTERY_LOW_OKAY, args)
                            .sendToTarget();
                } else {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
                                mBatteryOptions);
                                    BATTERY_OPTIONS);
                        }
                    });
                }
            } else if (mSentLowBatteryBroadcast &&
                    mHealthInfo.batteryLevel >= mLowBatteryCloseWarningLevel) {
                mSentLowBatteryBroadcast = false;
                final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                if (com.android.server.flags.Flags.consolidateBatteryChangeEvents()) {
                    mHandler.removeMessages(MSG_BROADCAST_BATTERY_LOW_OKAY);
                    final SomeArgs args = SomeArgs.obtain();
                    args.arg1 = mContext;
                    args.arg2 = statusIntent;
                    mHandler.obtainMessage(MSG_BROADCAST_BATTERY_LOW_OKAY, args)
                            .sendToTarget();
                } else {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
                                mBatteryOptions);
                                    BATTERY_OPTIONS);
                        }
                    });
                }
            }

            // We are doing this after sending the above broadcasts, so anything processing
            // them will get the new sequence number at that point.  (See for example how testing
@@ -777,8 +864,16 @@ public final class BatteryService extends SystemService {
                    + ", info:" + mHealthInfo.toString());
        }

        if (com.android.server.flags.Flags.consolidateBatteryChangeEvents()) {
            mHandler.removeMessages(MSG_BROADCAST_BATTERY_CHANGED);
            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = mContext;
            args.arg2 = intent;
            mHandler.obtainMessage(MSG_BROADCAST_BATTERY_CHANGED, args).sendToTarget();
        } else {
            mHandler.post(() -> broadcastBatteryChangedIntent(mContext,
                intent, mBatteryChangedOptions));
                    intent, BATTERY_CHANGED_OPTIONS));
        }
    }

    private static void broadcastBatteryChangedIntent(Context context, Intent intent,
@@ -1307,6 +1402,12 @@ public final class BatteryService extends SystemService {
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }

    @SuppressLint("AndroidFrameworkRequiresPermission")
    private static void sendBroadcastToAllUsers(Context context, Intent intent,
            Bundle options) {
        context.sendBroadcastAsUser(intent, UserHandle.ALL, null, options);
    }

    private final class Led {
        // must match: config_notificationsBatteryLowBehavior in config.xml
        static final int LOW_BATTERY_BEHAVIOR_DEFAULT = 0;
+11 −0
Original line number Diff line number Diff line
@@ -45,3 +45,14 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    namespace: "backstage_power"
    name: "consolidate_battery_change_events"
    description: "Optimize battery status updates by delivering only the most recent battery information"
    bug: "361334584"
    is_fixed_read_only: true
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}