diff options
author | Nate(Qiang) Jiang <qiangjiang@google.com> | 2019-10-22 13:08:35 -0700 |
---|---|---|
committer | Nate(Qiang) Jiang <qiangjiang@google.com> | 2019-11-07 13:14:38 -0800 |
commit | 194a506c9a5de993caee8888442db7bdb45de3e1 (patch) | |
tree | dd96e94499b64f97a93ef69aa3989bbe29b0e929 /service | |
parent | 4e74ff724a66310cc51f13fda8acc9bf6c43fa5f (diff) |
[NetworkSuggestion] add network callback
Add a network callback for WifiNetworkSuggestion. Will send event for
both connection success and failure.
Bug: 142062781
Test: atest android.net.wifi
Test: atest com.android.server.wifi
Change-Id: I46d403b784d469538118c9b03556b8236de35fe7
Diffstat (limited to 'service')
-rw-r--r-- | service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java | 112 | ||||
-rw-r--r-- | service/java/com/android/server/wifi/WifiServiceImpl.java | 46 |
2 files changed, 155 insertions, 3 deletions
diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java index a16d9684d..cbeb6284c 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java +++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java @@ -33,12 +33,15 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.MacAddress; +import android.net.wifi.ISuggestionConnectionStatusListener; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.WifiScanner; import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; import android.os.UserHandle; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -49,6 +52,7 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; +import com.android.server.wifi.util.ExternalCallbackTracker; import com.android.server.wifi.util.WifiPermissionsUtil; import java.io.FileDescriptor; @@ -239,6 +243,9 @@ public class WifiNetworkSuggestionsManager { private final Map<String, Set<ExtendedWifiNetworkSuggestion>> mPasspointInfo = new HashMap<>(); + private final HashMap<String, ExternalCallbackTracker<ISuggestionConnectionStatusListener>> + mSuggestionStatusListenerPerApp = new HashMap<>(); + /** * Intent filter for processing notification actions. */ @@ -764,6 +771,9 @@ public class WifiNetworkSuggestionsManager { removeInternal(Collections.EMPTY_LIST, packageName, perAppInfo); // Remove the package fully from the internal database. mActiveNetworkSuggestionsPerApp.remove(packageName); + ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenerTracker = + mSuggestionStatusListenerPerApp.remove(packageName); + if (listenerTracker != null) listenerTracker.clear(); saveToStore(); Log.i(TAG, "Removed " + packageName); } @@ -795,6 +805,7 @@ public class WifiNetworkSuggestionsManager { removeInternal(Collections.EMPTY_LIST, entry.getKey(), entry.getValue()); iter.remove(); } + mSuggestionStatusListenerPerApp.clear(); saveToStore(); Log.i(TAG, "Cleared all internal state"); } @@ -1090,6 +1101,7 @@ public class WifiNetworkSuggestionsManager { mWifiPermissionsUtil.enforceCanAccessScanResults( packageName, matchingSuggestion.suggestorUid); } catch (SecurityException se) { + Log.w(TAG, "Permission denied for sending post connection broadcast to " + packageName); return; } if (mVerboseLoggingEnabled) { @@ -1145,9 +1157,10 @@ public class WifiNetworkSuggestionsManager { * * @param network {@link WifiConfiguration} representing the network that connection failed to. * @param bssid BSSID of the network connection failed to if known, else null. + * @param failureCode failure reason code. */ private void handleConnectionFailure(@NonNull WifiConfiguration network, - @Nullable String bssid) { + @Nullable String bssid, int failureCode) { Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = getNetworkSuggestionsForWifiConfiguration(network, bssid); if (mVerboseLoggingEnabled) { @@ -1160,6 +1173,12 @@ public class WifiNetworkSuggestionsManager { mWifiMetrics.incrementNetworkSuggestionApiNumConnectFailure(); // TODO (b/115504887, b/112196799): Blacklist the corresponding network suggestion if // the connection failed. + + for (ExtendedWifiNetworkSuggestion matchingExtNetworkSuggestion + : matchingExtNetworkSuggestions) { + sendConnectionFailureIfAllowed(matchingExtNetworkSuggestion.perAppInfo.packageName, + matchingExtNetworkSuggestion.wns, failureCode); + } } private void resetConnectionState() { @@ -1182,7 +1201,7 @@ public class WifiNetworkSuggestionsManager { if (failureCode == WifiMetrics.ConnectionEvent.FAILURE_NONE) { handleConnectionSuccess(network, bssid); } else { - handleConnectionFailure(network, bssid); + handleConnectionFailure(network, bssid, failureCode); } } @@ -1197,6 +1216,95 @@ public class WifiNetworkSuggestionsManager { } /** + * Send network connection failure event to app when an connection attempt failure. + * @param packageName package name to send event + * @param matchingSuggestion suggestion on this connection failure + * @param connectionEvent connection failure code + */ + private void sendConnectionFailureIfAllowed(String packageName, + @NonNull WifiNetworkSuggestion matchingSuggestion, + int connectionEvent) { + ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenersTracker = + mSuggestionStatusListenerPerApp.get(packageName); + if (listenersTracker == null || listenersTracker.getNumCallbacks() == 0) { + return; + } + try { + mWifiPermissionsUtil.enforceCanAccessScanResults( + packageName, matchingSuggestion.suggestorUid); + } catch (SecurityException se) { + Log.w(TAG, "Permission denied for sending connection failure event to " + packageName); + return; + } + if (mVerboseLoggingEnabled) { + Log.v(TAG, "Sending connection failure event to " + packageName); + } + for (ISuggestionConnectionStatusListener listener : listenersTracker.getCallbacks()) { + try { + listener.onConnectionStatus(matchingSuggestion, + internalConnectionEventToSuggestionFailureCode(connectionEvent)); + } catch (RemoteException e) { + Log.e(TAG, "sendNetworkCallback: remote exception -- " + e); + } + } + } + + private @WifiManager.SuggestionConnectionStatusCode + int internalConnectionEventToSuggestionFailureCode(int connectionEvent) { + switch (connectionEvent) { + case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION: + case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT: + return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION; + case WifiMetrics.ConnectionEvent.FAILURE_SSID_TEMP_DISABLED: + case WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE: + return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION; + case WifiMetrics.ConnectionEvent.FAILURE_DHCP: + return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING; + default: + return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN; + } + + } + + /** + * Register a SuggestionConnectionStatusListener on network connection failure. + * @param binder IBinder instance to allow cleanup if the app dies. + * @param listener ISuggestionNetworkCallback instance to add. + * @param listenerIdentifier identifier of the listener, should be hash code of listener. + * @return true if succeed otherwise false. + */ + public boolean registerSuggestionConnectionStatusListener(@NonNull IBinder binder, + @NonNull ISuggestionConnectionStatusListener listener, + int listenerIdentifier, String packageName) { + ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenersTracker = + mSuggestionStatusListenerPerApp.get(packageName); + if (listenersTracker == null) { + listenersTracker = + new ExternalCallbackTracker<>(mHandler); + } + listenersTracker.add(binder, listener, listenerIdentifier); + mSuggestionStatusListenerPerApp.put(packageName, listenersTracker); + return true; + } + + /** + * Unregister a listener on network connection failure. + * @param listenerIdentifier identifier of the listener, should be hash code of listener. + */ + public void unregisterSuggestionConnectionStatusListener(int listenerIdentifier, + String packageName) { + ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenersTracker = + mSuggestionStatusListenerPerApp.get(packageName); + if (listenersTracker == null || listenersTracker.remove(listenerIdentifier) == null) { + Log.w(TAG, "unregisterSuggestionConnectionStatusListener: Listener[" + + listenerIdentifier + "] from " + packageName + " already unregister."); + } + if (listenersTracker.getNumCallbacks() == 0) { + mSuggestionStatusListenerPerApp.remove(packageName); + } + } + + /** * Dump of {@link WifiNetworkSuggestionsManager}. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index 8c398f5c3..fb2ea0f69 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -55,6 +55,7 @@ import android.net.wifi.INetworkRequestMatchCallback; import android.net.wifi.IOnWifiUsabilityStatsListener; import android.net.wifi.IScanResultsListener; import android.net.wifi.ISoftApCallback; +import android.net.wifi.ISuggestionConnectionStatusListener; import android.net.wifi.ITrafficStateCallback; import android.net.wifi.ITxPacketCountListener; import android.net.wifi.ScanResult; @@ -67,6 +68,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.DeviceMobilityState; import android.net.wifi.WifiManager.LocalOnlyHotspotCallback; +import android.net.wifi.WifiManager.SuggestionConnectionStatusListener; import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.WifiScanner; import android.net.wifi.WifiSsid; @@ -3479,7 +3481,7 @@ public class WifiServiceImpl extends BaseWifiService { /** * See {@link WifiManager#addScanResultsListener(Executor, WifiManager.ScanResultsListener)} */ - public void registerScanResultsListener(IBinder binder, IScanResultsListener listener, + public void registerScanResultsListener(IBinder binder, @NonNull IScanResultsListener listener, int listenerIdentifier) { if (binder == null) { throw new IllegalArgumentException("Binder must not be null"); @@ -3514,4 +3516,46 @@ public class WifiServiceImpl extends BaseWifiService { .unregisterScanResultsListener(listenerIdentifier)); } + + /** + * See {@link WifiManager#addSuggestionConnectionStatusListener(Executor, + * SuggestionConnectionStatusListener)} + */ + public void registerSuggestionConnectionStatusListener(IBinder binder, + @NonNull ISuggestionConnectionStatusListener listener, + int listenerIdentifier, String packageName) { + if (binder == null) { + throw new IllegalArgumentException("Binder must not be null"); + } + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + final int uid = Binder.getCallingUid(); + enforceAccessPermission(); + enforceLocationPermission(packageName, uid); + if (mVerboseLoggingEnabled) { + mLog.info("registerSuggestionConnectionStatusListener uid=%").c(uid).flush(); + } + mWifiThreadRunner.post(() -> + mWifiNetworkSuggestionsManager + .registerSuggestionConnectionStatusListener(binder, listener, + listenerIdentifier, packageName)); + } + + /** + * See {@link WifiManager#removeSuggestionConnectionStatusListener( + * SuggestionConnectionStatusListener)} + */ + public void unregisterSuggestionConnectionStatusListener( + int listenerIdentifier, String packageName) { + enforceAccessPermission(); + if (mVerboseLoggingEnabled) { + mLog.info("unregisterSuggestionConnectionStatusListener uid=%") + .c(Binder.getCallingUid()).flush(); + } + mWifiThreadRunner.post(() -> + mWifiNetworkSuggestionsManager + .unregisterSuggestionConnectionStatusListener(listenerIdentifier, + packageName)); + } } |