diff options
author | Rebecca Silberstein <silberst@google.com> | 2017-05-19 03:05:55 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-05-19 03:05:55 +0000 |
commit | 22dfcc6ab20d260c0318090386af91ea95724e99 (patch) | |
tree | 0e6dc9646d6d013a515964d8b4fadbb1d9f3a090 /service | |
parent | f4232f9036f66fd505786dff0a3d6e84f78c8168 (diff) | |
parent | 878e0cccd652ea556680b9cc101b01142e9ad919 (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.java | 48 | ||||
-rw-r--r-- | service/java/com/android/server/wifi/WifiServiceImpl.java | 132 |
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; } |