Files
frameworks_base/services/java/com/android/server/wifi/WifiController.java
Vinit Deshapnde 31727f8456 DO NOT MERGE - Fix Airplane Mode + reboot interaction for Wifi
This change fixes two problems - first, if you rebooted phone after
turning on Airplane mode, Wifi controller goes to ScanOnly mode which
may end up in Wifi radio transmissions. Secondly, because of this
incorrect state, the state machine doesn't turn on Wifi once Airplane
mode is turned off.

bug: 11409692
Change-Id: I55b4a5352a72a9c783e1b9891dd5363434585fb0
2014-03-05 17:14:49 -08:00

762 lines
30 KiB
Java

/*
* Copyright (C) 2013 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.wifi;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import static android.net.wifi.WifiManager.WIFI_MODE_FULL;
import static android.net.wifi.WifiManager.WIFI_MODE_FULL_HIGH_PERF;
import static android.net.wifi.WifiManager.WIFI_MODE_SCAN_ONLY;
import android.net.wifi.WifiStateMachine;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.os.WorkSource;
import android.provider.Settings;
import android.util.Slog;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.server.wifi.WifiService.LockList;
import java.io.FileDescriptor;
import java.io.PrintWriter;
class WifiController extends StateMachine {
private static final String TAG = "WifiController";
private static final boolean DBG = false;
private Context mContext;
private boolean mScreenOff;
private boolean mDeviceIdle;
private int mPluggedType;
private int mStayAwakeConditions;
private long mIdleMillis;
private int mSleepPolicy;
private boolean mFirstUserSignOnSeen = false;
private AlarmManager mAlarmManager;
private PendingIntent mIdleIntent;
private static final int IDLE_REQUEST = 0;
/**
* See {@link Settings.Global#WIFI_IDLE_MS}. This is the default value if a
* Settings.Global value is not present. This timeout value is chosen as
* the approximate point at which the battery drain caused by Wi-Fi
* being enabled but not active exceeds the battery drain caused by
* re-establishing a connection to the mobile data network.
*/
private static final long DEFAULT_IDLE_MS = 15 * 60 * 1000; /* 15 minutes */
/**
* See {@link Settings.Global#WIFI_REENABLE_DELAY_MS}. This is the default value if a
* Settings.Global value is not present. This is the minimum time after wifi is disabled
* we'll act on an enable. Enable requests received before this delay will be deferred.
*/
private static final long DEFAULT_REENABLE_DELAY_MS = 500;
// finding that delayed messages can sometimes be delivered earlier than expected
// probably rounding errors.. add a margin to prevent problems
private static final long DEFER_MARGIN_MS = 5;
NetworkInfo mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, "WIFI", "");
private static final String ACTION_DEVICE_IDLE =
"com.android.server.WifiManager.action.DEVICE_IDLE";
/* References to values tracked in WifiService */
final WifiStateMachine mWifiStateMachine;
final WifiSettingsStore mSettingsStore;
final LockList mLocks;
/**
* Temporary for computing UIDS that are responsible for starting WIFI.
* Protected by mWifiStateTracker lock.
*/
private final WorkSource mTmpWorkSource = new WorkSource();
private long mReEnableDelayMillis;
private static final int BASE = Protocol.BASE_WIFI_CONTROLLER;
static final int CMD_EMERGENCY_MODE_CHANGED = BASE + 1;
static final int CMD_SCREEN_ON = BASE + 2;
static final int CMD_SCREEN_OFF = BASE + 3;
static final int CMD_BATTERY_CHANGED = BASE + 4;
static final int CMD_DEVICE_IDLE = BASE + 5;
static final int CMD_LOCKS_CHANGED = BASE + 6;
static final int CMD_SCAN_ALWAYS_MODE_CHANGED = BASE + 7;
static final int CMD_WIFI_TOGGLED = BASE + 8;
static final int CMD_AIRPLANE_TOGGLED = BASE + 9;
static final int CMD_SET_AP = BASE + 10;
static final int CMD_DEFERRED_TOGGLE = BASE + 11;
static final int CMD_USER_PRESENT = BASE + 12;
private DefaultState mDefaultState = new DefaultState();
private StaEnabledState mStaEnabledState = new StaEnabledState();
private ApStaDisabledState mApStaDisabledState = new ApStaDisabledState();
private StaDisabledWithScanState mStaDisabledWithScanState = new StaDisabledWithScanState();
private ApEnabledState mApEnabledState = new ApEnabledState();
private DeviceActiveState mDeviceActiveState = new DeviceActiveState();
private DeviceInactiveState mDeviceInactiveState = new DeviceInactiveState();
private ScanOnlyLockHeldState mScanOnlyLockHeldState = new ScanOnlyLockHeldState();
private FullLockHeldState mFullLockHeldState = new FullLockHeldState();
private FullHighPerfLockHeldState mFullHighPerfLockHeldState = new FullHighPerfLockHeldState();
private NoLockHeldState mNoLockHeldState = new NoLockHeldState();
private EcmState mEcmState = new EcmState();
WifiController(Context context, WifiService service, Looper looper) {
super(TAG, looper);
mContext = context;
mWifiStateMachine = service.mWifiStateMachine;
mSettingsStore = service.mSettingsStore;
mLocks = service.mLocks;
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
mIdleIntent = PendingIntent.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);
addState(mDefaultState);
addState(mApStaDisabledState, mDefaultState);
addState(mStaEnabledState, mDefaultState);
addState(mDeviceActiveState, mStaEnabledState);
addState(mDeviceInactiveState, mStaEnabledState);
addState(mScanOnlyLockHeldState, mDeviceInactiveState);
addState(mFullLockHeldState, mDeviceInactiveState);
addState(mFullHighPerfLockHeldState, mDeviceInactiveState);
addState(mNoLockHeldState, mDeviceInactiveState);
addState(mStaDisabledWithScanState, mDefaultState);
addState(mApEnabledState, mDefaultState);
addState(mEcmState, mDefaultState);
boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
log("isAirplaneModeOn = " + isAirplaneModeOn +
", isWifiEnabled = " + isWifiEnabled +
", isScanningAvailable = " + isScanningAlwaysAvailable);
if (isWifiEnabled && isScanningAlwaysAvailable) {
setInitialState(mStaDisabledWithScanState);
} else {
setInitialState(mApStaDisabledState);
}
setLogRecSize(100);
setLogOnlyTransitions(false);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DEVICE_IDLE);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(ACTION_DEVICE_IDLE)) {
sendMessage(CMD_DEVICE_IDLE);
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO);
}
}
},
new IntentFilter(filter));
initializeAndRegisterForSettingsChange(looper);
}
private void initializeAndRegisterForSettingsChange(Looper looper) {
Handler handler = new Handler(looper);
readStayAwakeConditions();
registerForStayAwakeModeChange(handler);
readWifiIdleTime();
registerForWifiIdleTimeChange(handler);
readWifiSleepPolicy();
registerForWifiSleepPolicyChange(handler);
readWifiReEnableDelay();
}
private void readStayAwakeConditions() {
mStayAwakeConditions = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
}
private void readWifiIdleTime() {
mIdleMillis = Settings.Global.getLong(mContext.getContentResolver(),
Settings.Global.WIFI_IDLE_MS, DEFAULT_IDLE_MS);
}
private void readWifiSleepPolicy() {
mSleepPolicy = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.WIFI_SLEEP_POLICY,
Settings.Global.WIFI_SLEEP_POLICY_NEVER);
}
private void readWifiReEnableDelay() {
mReEnableDelayMillis = Settings.Global.getLong(mContext.getContentResolver(),
Settings.Global.WIFI_REENABLE_DELAY_MS, DEFAULT_REENABLE_DELAY_MS);
}
/**
* Observes settings changes to scan always mode.
*/
private void registerForStayAwakeModeChange(Handler handler) {
ContentObserver contentObserver = new ContentObserver(handler) {
@Override
public void onChange(boolean selfChange) {
readStayAwakeConditions();
}
};
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.STAY_ON_WHILE_PLUGGED_IN),
false, contentObserver);
}
/**
* Observes settings changes to scan always mode.
*/
private void registerForWifiIdleTimeChange(Handler handler) {
ContentObserver contentObserver = new ContentObserver(handler) {
@Override
public void onChange(boolean selfChange) {
readWifiIdleTime();
}
};
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.WIFI_IDLE_MS),
false, contentObserver);
}
/**
* Observes changes to wifi sleep policy
*/
private void registerForWifiSleepPolicyChange(Handler handler) {
ContentObserver contentObserver = new ContentObserver(handler) {
@Override
public void onChange(boolean selfChange) {
readWifiSleepPolicy();
}
};
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.WIFI_SLEEP_POLICY),
false, contentObserver);
}
/**
* Determines whether the Wi-Fi chipset should stay awake or be put to
* sleep. Looks at the setting for the sleep policy and the current
* conditions.
*
* @see #shouldDeviceStayAwake(int)
*/
private boolean shouldWifiStayAwake(int pluggedType) {
if (mSleepPolicy == Settings.Global.WIFI_SLEEP_POLICY_NEVER) {
// Never sleep
return true;
} else if ((mSleepPolicy == Settings.Global.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED) &&
(pluggedType != 0)) {
// Never sleep while plugged, and we're plugged
return true;
} else {
// Default
return shouldDeviceStayAwake(pluggedType);
}
}
/**
* Determine whether the bit value corresponding to {@code pluggedType} is set in
* the bit string mStayAwakeConditions. This determines whether the device should
* stay awake based on the current plugged type.
*
* @param pluggedType the type of plug (USB, AC, or none) for which the check is
* being made
* @return {@code true} if {@code pluggedType} indicates that the device is
* supposed to stay awake, {@code false} otherwise.
*/
private boolean shouldDeviceStayAwake(int pluggedType) {
return (mStayAwakeConditions & pluggedType) != 0;
}
private void updateBatteryWorkSource() {
mTmpWorkSource.clear();
if (mDeviceIdle) {
mLocks.updateWorkSource(mTmpWorkSource);
}
mWifiStateMachine.updateBatteryWorkSource(mTmpWorkSource);
}
class DefaultState extends State {
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_SCREEN_ON:
mAlarmManager.cancel(mIdleIntent);
mScreenOff = false;
mDeviceIdle = false;
updateBatteryWorkSource();
break;
case CMD_SCREEN_OFF:
mScreenOff = true;
/*
* Set a timer to put Wi-Fi to sleep, but only if the screen is off
* AND the "stay on while plugged in" setting doesn't match the
* current power conditions (i.e, not plugged in, plugged in to USB,
* or plugged in to AC).
*/
if (!shouldWifiStayAwake(mPluggedType)) {
//Delayed shutdown if wifi is connected
if (mNetworkInfo.getDetailedState() ==
NetworkInfo.DetailedState.CONNECTED) {
if (DBG) Slog.d(TAG, "set idle timer: " + mIdleMillis + " ms");
mAlarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + mIdleMillis, mIdleIntent);
} else {
sendMessage(CMD_DEVICE_IDLE);
}
}
break;
case CMD_DEVICE_IDLE:
mDeviceIdle = true;
updateBatteryWorkSource();
break;
case CMD_BATTERY_CHANGED:
/*
* Set a timer to put Wi-Fi to sleep, but only if the screen is off
* AND we are transitioning from a state in which the device was supposed
* to stay awake to a state in which it is not supposed to stay awake.
* If "stay awake" state is not changing, we do nothing, to avoid resetting
* the already-set timer.
*/
int pluggedType = msg.arg1;
if (DBG) Slog.d(TAG, "battery changed pluggedType: " + pluggedType);
if (mScreenOff && shouldWifiStayAwake(mPluggedType) &&
!shouldWifiStayAwake(pluggedType)) {
long triggerTime = System.currentTimeMillis() + mIdleMillis;
if (DBG) Slog.d(TAG, "set idle timer for " + mIdleMillis + "ms");
mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
}
mPluggedType = pluggedType;
break;
case CMD_SET_AP:
case CMD_SCAN_ALWAYS_MODE_CHANGED:
case CMD_LOCKS_CHANGED:
case CMD_WIFI_TOGGLED:
case CMD_AIRPLANE_TOGGLED:
case CMD_EMERGENCY_MODE_CHANGED:
break;
case CMD_USER_PRESENT:
mFirstUserSignOnSeen = true;
break;
case CMD_DEFERRED_TOGGLE:
log("DEFERRED_TOGGLE ignored due to state change");
break;
default:
throw new RuntimeException("WifiController.handleMessage " + msg.what);
}
return HANDLED;
}
}
class ApStaDisabledState extends State {
private int mDeferredEnableSerialNumber = 0;
private boolean mHaveDeferredEnable = false;
private long mDisabledTimestamp;
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(false);
// Supplicant can't restart right away, so not the time we switched off
mDisabledTimestamp = SystemClock.elapsedRealtime();
mDeferredEnableSerialNumber++;
mHaveDeferredEnable = false;
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
case CMD_AIRPLANE_TOGGLED:
if (mSettingsStore.isWifiToggleEnabled()) {
if (doDeferEnable(msg)) {
if (mHaveDeferredEnable) {
// have 2 toggles now, inc serial number an ignore both
mDeferredEnableSerialNumber++;
}
mHaveDeferredEnable = !mHaveDeferredEnable;
break;
}
if (mDeviceIdle == false) {
transitionTo(mDeviceActiveState);
} else {
checkLocksAndTransitionWhenDeviceIdle();
}
}
break;
case CMD_SCAN_ALWAYS_MODE_CHANGED:
if (mSettingsStore.isScanAlwaysAvailable()) {
transitionTo(mStaDisabledWithScanState);
}
break;
case CMD_SET_AP:
if (msg.arg1 == 1) {
mWifiStateMachine.setHostApRunning((WifiConfiguration) msg.obj,
true);
transitionTo(mApEnabledState);
}
break;
case CMD_DEFERRED_TOGGLE:
if (msg.arg1 != mDeferredEnableSerialNumber) {
log("DEFERRED_TOGGLE ignored due to serial mismatch");
break;
}
log("DEFERRED_TOGGLE handled");
sendMessage((Message)(msg.obj));
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
private boolean doDeferEnable(Message msg) {
long delaySoFar = SystemClock.elapsedRealtime() - mDisabledTimestamp;
if (delaySoFar >= mReEnableDelayMillis) {
return false;
}
log("WifiController msg " + msg + " deferred for " +
(mReEnableDelayMillis - delaySoFar) + "ms");
// need to defer this action.
Message deferredMsg = obtainMessage(CMD_DEFERRED_TOGGLE);
deferredMsg.obj = Message.obtain(msg);
deferredMsg.arg1 = ++mDeferredEnableSerialNumber;
sendMessageDelayed(deferredMsg, mReEnableDelayMillis - delaySoFar + DEFER_MARGIN_MS);
return true;
}
}
class StaEnabledState extends State {
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(true);
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
if (! mSettingsStore.isWifiToggleEnabled()) {
if (mSettingsStore.isScanAlwaysAvailable()) {
transitionTo(mStaDisabledWithScanState);
} else {
transitionTo(mApStaDisabledState);
}
}
break;
case CMD_AIRPLANE_TOGGLED:
/* When wi-fi is turned off due to airplane,
* disable entirely (including scan)
*/
if (! mSettingsStore.isWifiToggleEnabled()) {
transitionTo(mApStaDisabledState);
}
break;
case CMD_EMERGENCY_MODE_CHANGED:
if (msg.arg1 == 1) {
transitionTo(mEcmState);
break;
}
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
class StaDisabledWithScanState extends State {
private int mDeferredEnableSerialNumber = 0;
private boolean mHaveDeferredEnable = false;
private long mDisabledTimestamp;
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(true);
mWifiStateMachine.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE);
mWifiStateMachine.setDriverStart(true);
// Supplicant can't restart right away, so not the time we switched off
mDisabledTimestamp = SystemClock.elapsedRealtime();
mDeferredEnableSerialNumber++;
mHaveDeferredEnable = false;
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
if (mSettingsStore.isWifiToggleEnabled()) {
if (doDeferEnable(msg)) {
if (mHaveDeferredEnable) {
// have 2 toggles now, inc serial number and ignore both
mDeferredEnableSerialNumber++;
}
mHaveDeferredEnable = !mHaveDeferredEnable;
break;
}
if (mDeviceIdle == false) {
transitionTo(mDeviceActiveState);
} else {
checkLocksAndTransitionWhenDeviceIdle();
}
}
break;
case CMD_AIRPLANE_TOGGLED:
if (mSettingsStore.isAirplaneModeOn() &&
! mSettingsStore.isWifiToggleEnabled()) {
transitionTo(mApStaDisabledState);
}
case CMD_SCAN_ALWAYS_MODE_CHANGED:
if (! mSettingsStore.isScanAlwaysAvailable()) {
transitionTo(mApStaDisabledState);
}
break;
case CMD_SET_AP:
// Before starting tethering, turn off supplicant for scan mode
if (msg.arg1 == 1) {
deferMessage(msg);
transitionTo(mApStaDisabledState);
}
break;
case CMD_DEFERRED_TOGGLE:
if (msg.arg1 != mDeferredEnableSerialNumber) {
log("DEFERRED_TOGGLE ignored due to serial mismatch");
break;
}
logd("DEFERRED_TOGGLE handled");
sendMessage((Message)(msg.obj));
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
private boolean doDeferEnable(Message msg) {
long delaySoFar = SystemClock.elapsedRealtime() - mDisabledTimestamp;
if (delaySoFar >= mReEnableDelayMillis) {
return false;
}
log("WifiController msg " + msg + " deferred for " +
(mReEnableDelayMillis - delaySoFar) + "ms");
// need to defer this action.
Message deferredMsg = obtainMessage(CMD_DEFERRED_TOGGLE);
deferredMsg.obj = Message.obtain(msg);
deferredMsg.arg1 = ++mDeferredEnableSerialNumber;
sendMessageDelayed(deferredMsg, mReEnableDelayMillis - delaySoFar + DEFER_MARGIN_MS);
return true;
}
}
class ApEnabledState extends State {
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_AIRPLANE_TOGGLED:
if (mSettingsStore.isAirplaneModeOn()) {
mWifiStateMachine.setHostApRunning(null, false);
transitionTo(mApStaDisabledState);
}
break;
case CMD_SET_AP:
if (msg.arg1 == 0) {
mWifiStateMachine.setHostApRunning(null, false);
transitionTo(mApStaDisabledState);
}
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
class EcmState extends State {
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(false);
}
@Override
public boolean processMessage(Message msg) {
if (msg.what == CMD_EMERGENCY_MODE_CHANGED && msg.arg1 == 0) {
if (mSettingsStore.isWifiToggleEnabled()) {
if (mDeviceIdle == false) {
transitionTo(mDeviceActiveState);
} else {
checkLocksAndTransitionWhenDeviceIdle();
}
} else if (mSettingsStore.isScanAlwaysAvailable()) {
transitionTo(mStaDisabledWithScanState);
} else {
transitionTo(mApStaDisabledState);
}
return HANDLED;
} else {
return NOT_HANDLED;
}
}
}
/* Parent: StaEnabledState */
class DeviceActiveState extends State {
@Override
public void enter() {
mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
mWifiStateMachine.setDriverStart(true);
mWifiStateMachine.setHighPerfModeEnabled(false);
}
@Override
public boolean processMessage(Message msg) {
if (msg.what == CMD_DEVICE_IDLE) {
checkLocksAndTransitionWhenDeviceIdle();
// We let default state handle the rest of work
} else if (msg.what == CMD_USER_PRESENT) {
// TLS networks can't connect until user unlocks keystore. KeyStore
// unlocks when the user punches PIN after the reboot. So use this
// trigger to get those networks connected.
if (mFirstUserSignOnSeen == false) {
mWifiStateMachine.reloadTlsNetworksAndReconnect();
}
mFirstUserSignOnSeen = true;
return HANDLED;
}
return NOT_HANDLED;
}
}
/* Parent: StaEnabledState */
class DeviceInactiveState extends State {
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_LOCKS_CHANGED:
checkLocksAndTransitionWhenDeviceIdle();
updateBatteryWorkSource();
return HANDLED;
case CMD_SCREEN_ON:
transitionTo(mDeviceActiveState);
// More work in default state
return NOT_HANDLED;
default:
return NOT_HANDLED;
}
}
}
/* Parent: DeviceInactiveState. Device is inactive, but an app is holding a scan only lock. */
class ScanOnlyLockHeldState extends State {
@Override
public void enter() {
mWifiStateMachine.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
mWifiStateMachine.setDriverStart(true);
}
}
/* Parent: DeviceInactiveState. Device is inactive, but an app is holding a full lock. */
class FullLockHeldState extends State {
@Override
public void enter() {
mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
mWifiStateMachine.setDriverStart(true);
mWifiStateMachine.setHighPerfModeEnabled(false);
}
}
/* Parent: DeviceInactiveState. Device is inactive, but an app is holding a high perf lock. */
class FullHighPerfLockHeldState extends State {
@Override
public void enter() {
mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
mWifiStateMachine.setDriverStart(true);
mWifiStateMachine.setHighPerfModeEnabled(true);
}
}
/* Parent: DeviceInactiveState. Device is inactive and no app is holding a wifi lock. */
class NoLockHeldState extends State {
@Override
public void enter() {
mWifiStateMachine.setDriverStart(false);
}
}
private void checkLocksAndTransitionWhenDeviceIdle() {
if (mLocks.hasLocks()) {
switch (mLocks.getStrongestLockMode()) {
case WIFI_MODE_FULL:
transitionTo(mFullLockHeldState);
break;
case WIFI_MODE_FULL_HIGH_PERF:
transitionTo(mFullHighPerfLockHeldState);
break;
case WIFI_MODE_SCAN_ONLY:
transitionTo(mScanOnlyLockHeldState);
break;
default:
loge("Illegal lock " + mLocks.getStrongestLockMode());
}
} else {
if (mSettingsStore.isScanAlwaysAvailable()) {
transitionTo(mScanOnlyLockHeldState);
} else {
transitionTo(mNoLockHeldState);
}
}
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
super.dump(fd, pw, args);
pw.println("mScreenOff " + mScreenOff);
pw.println("mDeviceIdle " + mDeviceIdle);
pw.println("mPluggedType " + mPluggedType);
pw.println("mIdleMillis " + mIdleMillis);
pw.println("mSleepPolicy " + mSleepPolicy);
}
}