summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorRebecca Silberstein <silberst@google.com>2017-05-19 03:05:55 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2017-05-19 03:05:55 +0000
commit22dfcc6ab20d260c0318090386af91ea95724e99 (patch)
tree0e6dc9646d6d013a515964d8b4fadbb1d9f3a090 /service
parentf4232f9036f66fd505786dff0a3d6e84f78c8168 (diff)
parent878e0cccd652ea556680b9cc101b01142e9ad919 (diff)
Merge "WifiServiceImpl: listen and act on softap changes" into oc-dev
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java48
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java132
2 files changed, 168 insertions, 12 deletions
diff --git a/service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java b/service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java
index 2925d966b..9e3b4fb2c 100644
--- a/service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java
+++ b/service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java
@@ -17,6 +17,8 @@
package com.android.server.wifi;
import android.annotation.NonNull;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.Message;
@@ -31,7 +33,9 @@ import com.android.internal.util.Preconditions;
* @hide
*/
public class LocalOnlyHotspotRequestInfo implements IBinder.DeathRecipient {
- private final int mUid;
+ static final int HOTSPOT_NO_ERROR = -1;
+
+ private final int mPid;
private final IBinder mBinder;
private final RequestingApplicationDeathCallback mCallback;
private final Messenger mMessenger;
@@ -48,7 +52,7 @@ public class LocalOnlyHotspotRequestInfo implements IBinder.DeathRecipient {
LocalOnlyHotspotRequestInfo(@NonNull IBinder binder, @NonNull Messenger messenger,
@NonNull RequestingApplicationDeathCallback callback) {
- mUid = Binder.getCallingUid();
+ mPid = Binder.getCallingPid();
mBinder = Preconditions.checkNotNull(binder);
mMessenger = Preconditions.checkNotNull(messenger);
mCallback = Preconditions.checkNotNull(callback);
@@ -76,21 +80,45 @@ public class LocalOnlyHotspotRequestInfo implements IBinder.DeathRecipient {
}
/**
- * Send a message to WifiManager for the calling application.
+ * Send a HOTSPOT_FAILED message to WifiManager for the calling application with the error code.
+ *
+ * @param reasonCode error code for the message
+ *
+ * @throws RemoteException
+ */
+ public void sendHotspotFailedMessage(int reasonCode) throws RemoteException {
+ Message message = Message.obtain();
+ message.what = WifiManager.HOTSPOT_FAILED;
+ message.arg1 = reasonCode;
+ mMessenger.send(message);
+ }
+
+ /**
+ * Send a HOTSPOT_STARTED message to WifiManager for the calling application with the config.
+ *
+ * @param config WifiConfiguration for the callback
*
- * @param what Message type to send
- * @param arg1 arg1 for the message
+ * @throws RemoteException
+ */
+ public void sendHotspotStartedMessage(WifiConfiguration config) throws RemoteException {
+ Message message = Message.obtain();
+ message.what = WifiManager.HOTSPOT_STARTED;
+ message.obj = config;
+ mMessenger.send(message);
+ }
+
+ /**
+ * Send a HOTSPOT_STOPPED message to WifiManager for the calling application.
*
* @throws RemoteException
*/
- public void sendMessage(int what, int arg1) throws RemoteException {
+ public void sendHotspotStoppedMessage() throws RemoteException {
Message message = Message.obtain();
- message.what = what;
- message.arg1 = arg1;
+ message.what = WifiManager.HOTSPOT_STOPPED;
mMessenger.send(message);
}
- public int getUid() {
- return mUid;
+ public int getPid() {
+ return mPid;
}
}
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 6a5c6d2f5..ce9784d2e 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -16,7 +16,18 @@
package com.android.server.wifi;
+import static android.net.wifi.WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_FAILURE_REASON;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
+import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC;
+import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL;
+import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
+
import static com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED;
+import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR;
import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED;
import static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED;
import static com.android.server.wifi.WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED;
@@ -475,6 +486,21 @@ public class WifiServiceImpl extends IWifiManager.Stub {
},
new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED));
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final int currentState = intent.getIntExtra(EXTRA_WIFI_AP_STATE,
+ WIFI_AP_STATE_DISABLED);
+ final int prevState = intent.getIntExtra(EXTRA_PREVIOUS_WIFI_AP_STATE,
+ WIFI_AP_STATE_DISABLED);
+ final int errorCode = intent.getIntExtra(EXTRA_WIFI_AP_FAILURE_REASON,
+ HOTSPOT_NO_ERROR);
+ handleWifiApStateChange(currentState, prevState, errorCode);
+ }
+ },
+ new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_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.
@@ -907,6 +933,108 @@ public class WifiServiceImpl extends IWifiManager.Stub {
}
/**
+ * Private method to handle SoftAp state changes
+ */
+ private void handleWifiApStateChange(int currentState, int previousState, int errorCode) {
+ // The AP state update from WifiStateMachine for softap
+ Slog.d(TAG, "handleWifiApStateChange: currentState=" + currentState
+ + " previousState=" + previousState + " errorCode= " + errorCode);
+
+ // check if we have a failure - since it is possible (worst case scenario where
+ // WifiController and WifiStateMachine are out of sync wrt modes) to get two FAILED
+ // notifications in a row, we need to handle this first.
+ if (currentState == WIFI_AP_STATE_FAILED) {
+ // update registered LOHS callbacks if we see a failure
+ synchronized (mLocalOnlyHotspotRequests) {
+ int errorToReport = ERROR_GENERIC;
+ if (errorCode == SAP_START_FAILURE_NO_CHANNEL) {
+ errorToReport = ERROR_NO_CHANNEL;
+ }
+ // holding the required lock: send message to requestors and clear the list
+ sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(
+ errorToReport);
+ }
+ return;
+ }
+
+ if (currentState == WIFI_AP_STATE_DISABLING || currentState == WIFI_AP_STATE_DISABLED) {
+ // softap is shutting down or is down... let requestors know via the onStopped call
+ synchronized (mLocalOnlyHotspotRequests) {
+ // holding the required lock: send message to requestors and clear the list
+ sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked();
+ }
+ return;
+ }
+
+ // remaining states are enabling or enabled... those are not used for the callbacks
+ }
+
+ /**
+ * Helper method to send a HOTSPOT_FAILED message to all registered LocalOnlyHotspotRequest
+ * callers and clear the registrations.
+ *
+ * Callers should already hold the mLocalOnlyHotspotRequests lock.
+ */
+ private void sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(int arg1) {
+ for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) {
+ try {
+ requestor.sendHotspotFailedMessage(arg1);
+ } catch (RemoteException e) {
+ // This will be cleaned up by binder death handling
+ }
+ }
+
+ // Since all callers were notified, now clear the registrations.
+ mLocalOnlyHotspotRequests.clear();
+ }
+
+ /**
+ * Helper method to send a HOTSPOT_STOPPED message to all registered LocalOnlyHotspotRequest
+ * callers and clear the registrations.
+ *
+ * Callers should already hold the mLocalOnlyHotspotRequests lock.
+ */
+ private void sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked() {
+ for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) {
+ try {
+ requestor.sendHotspotStoppedMessage();
+ } catch (RemoteException e) {
+ // This will be cleaned up by binder death handling
+ }
+ }
+
+ // Since all callers were notified, now clear the registrations.
+ mLocalOnlyHotspotRequests.clear();
+ }
+
+ /**
+ * Helper method to send a HOTSPOT_STARTED message to all registered LocalOnlyHotspotRequest
+ * callers.
+ *
+ * Callers should already hold the mLocalOnlyHotspotRequests lock.
+ */
+ private void sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked() {
+ for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) {
+ try {
+ requestor.sendHotspotStartedMessage(mLocalOnlyHotspotConfig);
+ } catch (RemoteException e) {
+ // This will be cleaned up by binder death handling
+ }
+ }
+ }
+
+ /**
+ * Temporary method used for testing while startLocalOnlyHotspot is not fully implemented. This
+ * method allows unit tests to register callbacks directly for testing mechanisms triggered by
+ * softap mode changes.
+ * TODO: remove when startLocalOnlyHotspot is implemented.
+ */
+ @VisibleForTesting
+ void registerLOHSForTest(int pid, LocalOnlyHotspotRequestInfo request) {
+ mLocalOnlyHotspotRequests.put(pid, request);
+ }
+
+ /**
* Method to start LocalOnlyHotspot. In this method, permissions, settings and modes are
* checked to verify that we can enter softapmode. This method returns
* {@link LocalOnlyHotspotCallback#REQUEST_REGISTERED} if we will attempt to start, otherwise,
@@ -980,10 +1108,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* Helper method to unregister LocalOnlyHotspot requestors and stop the hotspot if needed.
*/
private void unregisterCallingAppAndStopLocalOnlyHotspot(LocalOnlyHotspotRequestInfo request) {
- mLog.trace("unregisterCallingAppAndStopLocalOnlyHotspot uid=%").c(request.getUid()).flush();
+ mLog.trace("unregisterCallingAppAndStopLocalOnlyHotspot pid=%").c(request.getPid()).flush();
synchronized (mLocalOnlyHotspotRequests) {
- if (mLocalOnlyHotspotRequests.remove(request.getUid()) == null) {
+ if (mLocalOnlyHotspotRequests.remove(request.getPid()) == null) {
mLog.trace("LocalOnlyHotspotRequestInfo not found to remove");
return;
}