diff options
Diffstat (limited to 'service/java/com/android/server/wifi/WifiController.java')
-rw-r--r-- | service/java/com/android/server/wifi/WifiController.java | 195 |
1 files changed, 164 insertions, 31 deletions
diff --git a/service/java/com/android/server/wifi/WifiController.java b/service/java/com/android/server/wifi/WifiController.java index 9a8967b..a22f985 100644 --- a/service/java/com/android/server/wifi/WifiController.java +++ b/service/java/com/android/server/wifi/WifiController.java @@ -36,8 +36,12 @@ import android.os.Message; import android.os.SystemClock; import android.os.WorkSource; import android.provider.Settings; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; import android.util.Slog; +import android.widget.Toast; import com.android.internal.util.Protocol; import com.android.internal.util.State; import com.android.internal.util.StateMachine; @@ -57,21 +61,13 @@ class WifiController extends StateMachine { private long mIdleMillis; private int mSleepPolicy; private boolean mFirstUserSignOnSeen = false; + private int mDefaultWifiIdleMs; 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. @@ -102,19 +98,20 @@ class WifiController extends StateMachine { 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; - static final int CMD_AP_START_FAILURE = BASE + 13; + 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; + static final int CMD_AP_START_FAILURE = BASE + 13; + static final int CMD_EMERGENCY_CALL_STATE_CHANGED = BASE + 14; private static final int WIFI_DISABLED = 0; private static final int WIFI_ENABLED = 1; @@ -125,6 +122,7 @@ class WifiController extends StateMachine { private StaDisabledWithScanState mStaDisabledWithScanState = new StaDisabledWithScanState(); private ApEnabledState mApEnabledState = new ApEnabledState(); private DeviceActiveState mDeviceActiveState = new DeviceActiveState(); + private DeviceActiveHighPerfState mDeviceActiveHighPerfState = new DeviceActiveHighPerfState(); private DeviceInactiveState mDeviceInactiveState = new DeviceInactiveState(); private ScanOnlyLockHeldState mScanOnlyLockHeldState = new ScanOnlyLockHeldState(); private FullLockHeldState mFullLockHeldState = new FullLockHeldState(); @@ -138,6 +136,8 @@ class WifiController extends StateMachine { mWifiStateMachine = service.mWifiStateMachine; mSettingsStore = service.mSettingsStore; mLocks = service.mLocks; + mDefaultWifiIdleMs = context.getResources().getInteger(com.android.internal. + R.integer.def_wifi_idle_ms); mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null); @@ -147,6 +147,7 @@ class WifiController extends StateMachine { addState(mApStaDisabledState, mDefaultState); addState(mStaEnabledState, mDefaultState); addState(mDeviceActiveState, mStaEnabledState); + addState(mDeviceActiveHighPerfState, mDeviceActiveState); addState(mDeviceInactiveState, mStaEnabledState); addState(mScanOnlyLockHeldState, mDeviceInactiveState); addState(mFullLockHeldState, mDeviceInactiveState); @@ -221,7 +222,7 @@ class WifiController extends StateMachine { private void readWifiIdleTime() { mIdleMillis = Settings.Global.getLong(mContext.getContentResolver(), - Settings.Global.WIFI_IDLE_MS, DEFAULT_IDLE_MS); + Settings.Global.WIFI_IDLE_MS, mDefaultWifiIdleMs); } private void readWifiSleepPolicy() { @@ -384,6 +385,7 @@ class WifiController extends StateMachine { case CMD_WIFI_TOGGLED: case CMD_AIRPLANE_TOGGLED: case CMD_EMERGENCY_MODE_CHANGED: + case CMD_EMERGENCY_CALL_STATE_CHANGED: case CMD_AP_START_FAILURE: break; case CMD_USER_PRESENT: @@ -429,7 +431,7 @@ class WifiController extends StateMachine { break; } if (mDeviceIdle == false) { - transitionTo(mDeviceActiveState); + checkLocksAndTransitionWhenDeviceActive(); } else { checkLocksAndTransitionWhenDeviceIdle(); } @@ -511,6 +513,7 @@ class WifiController extends StateMachine { transitionTo(mApStaDisabledState); } break; + case CMD_EMERGENCY_CALL_STATE_CHANGED: case CMD_EMERGENCY_MODE_CHANGED: if (msg.arg1 == 1) { transitionTo(mEcmState); @@ -564,7 +567,7 @@ class WifiController extends StateMachine { break; } if (mDeviceIdle == false) { - transitionTo(mDeviceActiveState); + checkLocksAndTransitionWhenDeviceActive(); } else { checkLocksAndTransitionWhenDeviceIdle(); } @@ -623,6 +626,74 @@ class WifiController extends StateMachine { } class ApEnabledState extends State { + + private SubscriptionManager.OnSubscriptionsChangedListener mSubListener; + + @Override + public void enter() { + mSubListener = new SubscriptionManager.OnSubscriptionsChangedListener() { + boolean firstChange = true; + SubscriptionInfo lastSub; + String lastSubscriberId; + + @Override + public void onSubscriptionsChanged() { + TelephonyManager tm = (TelephonyManager) + mContext.getSystemService(Context.TELEPHONY_SERVICE); + final SubscriptionInfo currentSub = SubscriptionManager.from(mContext) + .getDefaultDataSubscriptionInfo(); + + if (currentSub == null) { + // don't disable when we're not sure yet. + return; + } + + String currentSubscriberId = + tm.getSubscriberId(currentSub.getSubscriptionId()); + + if (currentSubscriberId == null) { + // don't disable when we're not sure yet. + return; + } + + if (firstChange) { + lastSub = currentSub; + lastSubscriberId = currentSubscriberId; + // we always get a state change on registration. + firstChange = false; + return; + } + + // SubscriptionInfo#getSubscriptionId() returns a + // framework handle and is not an IMSI. Don't use it to + // determine if the sub changed. + // + // TelephonyManager#getSubscriberId() returns the IMSI, + // so use that instead + if (currentSubscriberId.equals(lastSubscriberId)) { + // don't disable if it's the same subscription + return; + } + + lastSub = currentSub; + lastSubscriberId = currentSubscriberId; + + Toast.makeText(mContext, + com.android.internal.R.string.subscription_change_disabled_wifi_ap, + Toast.LENGTH_SHORT).show(); + log("disabling Wifi AP due to Subscriber Id (IMSI) change"); + WifiController.this.obtainMessage(CMD_SET_AP, 0, 0, null).sendToTarget(); + } + }; + SubscriptionManager.from(mContext).addOnSubscriptionsChangedListener(mSubListener); + } + + @Override + public void exit() { + SubscriptionManager.from(mContext).removeOnSubscriptionsChangedListener(mSubListener); + mSubListener = null; + } + @Override public boolean processMessage(Message msg) { switch (msg.what) { @@ -650,6 +721,7 @@ class WifiController extends StateMachine { } } break; + case CMD_EMERGENCY_CALL_STATE_CHANGED: case CMD_EMERGENCY_MODE_CHANGED: if (msg.arg1 == 1) { mWifiStateMachine.setHostApRunning(null, false); @@ -670,18 +742,58 @@ class WifiController extends StateMachine { } class EcmState extends State { + // we can enter EcmState either because an emergency call started or because + // emergency callback mode started. This count keeps track of how many such + // events happened; so we can exit after all are undone + + private int mEcmEntryCount; @Override public void enter() { mWifiStateMachine.setSupplicantRunning(false); mWifiStateMachine.clearANQPCache(); + mEcmEntryCount = 1; } @Override public boolean processMessage(Message msg) { - if (msg.what == CMD_EMERGENCY_MODE_CHANGED && msg.arg1 == 0) { + if (msg.what == CMD_EMERGENCY_CALL_STATE_CHANGED) { + if (msg.arg1 == 1) { + // nothing to do - just says emergency call started + mEcmEntryCount++; + } else if (msg.arg1 == 0) { + // emergency call ended + decrementCountAndReturnToAppropriateState(); + } + return HANDLED; + } else if (msg.what == CMD_EMERGENCY_MODE_CHANGED) { + + if (msg.arg1 == 1) { + // Transitioned into emergency callback mode + mEcmEntryCount++; + } else if (msg.arg1 == 0) { + // out of emergency callback mode + decrementCountAndReturnToAppropriateState(); + } + return HANDLED; + } else { + return NOT_HANDLED; + } + } + + private void decrementCountAndReturnToAppropriateState() { + boolean exitEcm = false; + + if (mEcmEntryCount == 0) { + loge("mEcmEntryCount is 0; exiting Ecm"); + exitEcm = true; + } else if (--mEcmEntryCount == 0) { + exitEcm = true; + } + + if (exitEcm) { if (mSettingsStore.isWifiToggleEnabled()) { if (mDeviceIdle == false) { - transitionTo(mDeviceActiveState); + checkLocksAndTransitionWhenDeviceActive(); } else { checkLocksAndTransitionWhenDeviceIdle(); } @@ -690,9 +802,6 @@ class WifiController extends StateMachine { } else { transitionTo(mApStaDisabledState); } - return HANDLED; - } else { - return NOT_HANDLED; } } } @@ -711,6 +820,9 @@ class WifiController extends StateMachine { if (msg.what == CMD_DEVICE_IDLE) { checkLocksAndTransitionWhenDeviceIdle(); // We let default state handle the rest of work + } else if (msg.what == CMD_LOCKS_CHANGED) { + checkLocksAndTransitionWhenDeviceActive(); + return HANDLED; } 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 @@ -725,6 +837,16 @@ class WifiController extends StateMachine { } } + /* Parent: DeviceActiveState. Device is active, and an app is holding a high perf lock. */ + class DeviceActiveHighPerfState extends State { + @Override + public void enter() { + mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE); + mWifiStateMachine.setDriverStart(true); + mWifiStateMachine.setHighPerfModeEnabled(true); + } + } + /* Parent: StaEnabledState */ class DeviceInactiveState extends State { @Override @@ -735,7 +857,7 @@ class WifiController extends StateMachine { updateBatteryWorkSource(); return HANDLED; case CMD_SCREEN_ON: - transitionTo(mDeviceActiveState); + checkLocksAndTransitionWhenDeviceActive(); // More work in default state return NOT_HANDLED; default: @@ -781,6 +903,17 @@ class WifiController extends StateMachine { } } + private void checkLocksAndTransitionWhenDeviceActive() { + if (mLocks.hasLocks() && mLocks.getStrongestLockMode() == WIFI_MODE_FULL_HIGH_PERF) { + // It is possible for the screen to be off while the device is + // is active (mIdleMillis), so we need the high-perf mode + // otherwise powersaving mode will be turned on. + transitionTo(mDeviceActiveHighPerfState); + } else { + transitionTo(mDeviceActiveState); + } + } + private void checkLocksAndTransitionWhenDeviceIdle() { if (mLocks.hasLocks()) { switch (mLocks.getStrongestLockMode()) { |