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

Commit 89710842 authored by Robert Greenwalt's avatar Robert Greenwalt
Browse files

Fix power issues around wifi scans.

- Sending a broadcast indicating when scan requests could be serviced so that
apps don't request scans we won't do anything with.
- Fix our batt stats accounting so we only count it if we send the request to
the driver.

bug: 8868201
bug: 9496690
Change-Id: I64a4f1c294c848ac64c50d8854ed4a6a1a47f603
parent f285a709
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@
    <protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
    <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
    <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
    <protected-broadcast android:name="android.net.wifi.WIFI_SCAN_AVAILABLE" />
    <protected-broadcast android:name="android.net.wifi.SCAN_RESULTS" />
    <protected-broadcast android:name="android.net.wifi.RSSI_CHANGED" />
    <protected-broadcast android:name="android.net.wifi.STATE_CHANGE" />
+1 −55
Original line number Diff line number Diff line
@@ -114,10 +114,6 @@ public final class WifiService extends IWifiManager.Stub {
    /* Tracks the persisted states for wi-fi & airplane mode */
    final WifiSettingsStore mSettingsStore;

    /* The work source (UID) that triggered the current WIFI scan, synchronized
     * on this */
    private WorkSource mScanWorkSource;

    /**
     * Asynchronous channel to WifiStateMachine
     */
@@ -255,17 +251,6 @@ public final class WifiService extends IWifiManager.Stub {
                },
                new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));

        mContext.registerReceiver(
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        if (intent.getAction().equals(
                                WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
                            noteScanEnd();
                        }
                    }
                }, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

        // Adding optimizations of only receiving broadcasts when wifi is enabled
        // can result in race conditions when apps toggle wifi in the background
        // without active user involvement. Always receive broadcasts.
@@ -274,44 +259,6 @@ public final class WifiService extends IWifiManager.Stub {

    private WifiController mWifiController;

    /** Tell battery stats about a new WIFI scan */
    private void noteScanStart() {
        WorkSource scanWorkSource = null;
        synchronized (WifiService.this) {
            if (mScanWorkSource != null) {
                // Scan already in progress, don't add this one to battery stats
                return;
            }
            scanWorkSource = new WorkSource(Binder.getCallingUid());
            mScanWorkSource = scanWorkSource;
        }

        long id = Binder.clearCallingIdentity();
        try {
            mBatteryStats.noteWifiScanStartedFromSource(scanWorkSource);
        } catch (RemoteException e) {
            Log.w(TAG, e);
        } finally {
            Binder.restoreCallingIdentity(id);
        }
    }

    /** Tell battery stats that the current WIFI scan has completed */
    private void noteScanEnd() {
        WorkSource scanWorkSource = null;
        synchronized (WifiService.this) {
            scanWorkSource = mScanWorkSource;
            mScanWorkSource = null;
        }
        if (scanWorkSource != null) {
            try {
                mBatteryStats.noteWifiScanStoppedFromSource(scanWorkSource);
            } catch (RemoteException e) {
                Log.w(TAG, e);
            }
        }
    }

    /**
     * Check if Wi-Fi needs to be enabled and start
     * if needed
@@ -352,8 +299,7 @@ public final class WifiService extends IWifiManager.Stub {
     */
    public void startScan() {
        enforceChangePermission();
        mWifiStateMachine.startScan();
        noteScanStart();
        mWifiStateMachine.startScan(Binder.getCallingUid());
    }

    private void enforceAccessPermission() {
+12 −0
Original line number Diff line number Diff line
@@ -69,6 +69,18 @@ public class WifiManager {
     */
    public static final int ERROR_AUTHENTICATING = 1;

    /**
     * Broadcast intent action indicating whether Wi-Fi scanning is allowed currently
     * @hide
     */
    public static final String WIFI_SCAN_AVAILABLE = "wifi_scan_available";

    /**
     * Extra int indicating scan availability, WIFI_STATE_ENABLED and WIFI_STATE_DISABLED
     * @hide
     */
     public static final String EXTRA_SCAN_AVAILABLE = "scan_enabled";

    /**
     * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
     * enabling, disabling, or unknown. One extra provides this state as an int.
+51 −5
Original line number Diff line number Diff line
@@ -141,6 +141,8 @@ public class WifiStateMachine extends StateMachine {
    */
    private int mOperationalMode = CONNECT_MODE;
    private boolean mScanResultIsPending = false;
    private WorkSource mScanWorkSource = null;
    private static final int UNKNOWN_SCAN_SOURCE = -1;
    /* Tracks if state machine has received any screen state change broadcast yet.
     * We can miss one of these at boot.
     */
@@ -601,7 +603,7 @@ public class WifiStateMachine extends StateMachine {
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        startScan();
                        startScan(UNKNOWN_SCAN_SOURCE);
                    }
                },
                new IntentFilter(ACTION_START_SCAN));
@@ -694,6 +696,11 @@ public class WifiStateMachine extends StateMachine {

        //start the state machine
        start();

        final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
    }

    /*********************************************************
@@ -716,8 +723,31 @@ public class WifiStateMachine extends StateMachine {
    /**
     * TODO: doc
     */
    public void startScan() {
        sendMessage(CMD_START_SCAN);
    public void startScan(int callingUid) {
        sendMessage(CMD_START_SCAN, callingUid);
    }

    private void noteScanStart(int callingUid) {
        if (mScanWorkSource == null && callingUid != UNKNOWN_SCAN_SOURCE) {
            mScanWorkSource = new WorkSource(callingUid);
            try {
                mBatteryStats.noteWifiScanStartedFromSource(mScanWorkSource);
            } catch (RemoteException e) {
                log(e.toString());
            }
        }
    }

    private void noteScanEnd() {
        if (mScanWorkSource != null) {
            try {
                mBatteryStats.noteWifiScanStoppedFromSource(mScanWorkSource);
            } catch (RemoteException e) {
                log(e.toString());
            } finally {
                mScanWorkSource = null;
            }
        }
    }

    private void startScanNative(int type) {
@@ -1575,6 +1605,7 @@ public class WifiStateMachine extends StateMachine {
    }

    private void sendScanResultsAvailableBroadcast() {
        noteScanEnd();
        Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
@@ -1919,6 +1950,7 @@ public class WifiStateMachine extends StateMachine {
                    }
                    break;
                    /* Discard */
                case CMD_START_SCAN:
                case CMD_START_SUPPLICANT:
                case CMD_STOP_SUPPLICANT:
                case CMD_STOP_SUPPLICANT_FAILED:
@@ -1933,7 +1965,6 @@ public class WifiStateMachine extends StateMachine {
                case CMD_STOP_AP:
                case CMD_TETHER_STATE_CHANGE:
                case CMD_TETHER_NOTIFICATION_TIMED_OUT:
                case CMD_START_SCAN:
                case CMD_DISCONNECT:
                case CMD_RECONNECT:
                case CMD_REASSOCIATE:
@@ -2436,11 +2467,18 @@ public class WifiStateMachine extends StateMachine {
            mWifiNative.setPowerSave(true);

            if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);

            final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
            intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED);
            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
        }

        @Override
        public boolean processMessage(Message message) {
            switch(message.what) {
                case CMD_START_SCAN:
                    noteScanStart(message.arg1);
                    startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);
                    break;
                case CMD_SET_COUNTRY_CODE:
@@ -2561,6 +2599,12 @@ public class WifiStateMachine extends StateMachine {
            mIsRunning = false;
            updateBatteryWorkSource(null);
            mScanResults = new ArrayList<ScanResult>();

            final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
            intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
            noteScanEnd(); // wrap up any pending request.
        }
    }

@@ -2711,6 +2755,7 @@ public class WifiStateMachine extends StateMachine {
                // Handle scan. All the connection related commands are
                // handled only in ConnectModeState
                case CMD_START_SCAN:
                    noteScanStart(message.arg1);
                    startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP);
                    break;
                default:
@@ -2974,6 +3019,7 @@ public class WifiStateMachine extends StateMachine {
                    break;
                case CMD_START_SCAN:
                    /* Do not attempt to connect when we are already connected */
                    noteScanStart(message.arg1);
                    startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP);
                    break;
                    /* Ignore connection to same network */
@@ -3291,7 +3337,7 @@ public class WifiStateMachine extends StateMachine {
                    if (mP2pConnected.get()) break;
                    if (message.arg1 == mPeriodicScanToken &&
                            mWifiConfigStore.getConfiguredNetworks().size() == 0) {
                        sendMessage(CMD_START_SCAN);
                        sendMessage(CMD_START_SCAN, UNKNOWN_SCAN_SOURCE);
                        sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
                                    ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
                    }