diff options
| author | 2020-01-17 16:07:08 +0000 | |
|---|---|---|
| committer | 2020-01-17 16:07:08 +0000 | |
| commit | 71c3dbac87377edaadd0f277e363f791df96a8e5 (patch) | |
| tree | c32c2ccccced7df281984a83d2b545f0859330a6 | |
| parent | df747d155ee8a3830fc9cf7dd46669f3472d2370 (diff) | |
| parent | ec6f8ce6fdde7a16e9d5cb2af93fb9b635909f3e (diff) | |
Merge "Extension API: Create System APIs to allow OEM module to override WiFi scorer in AOSP"
| -rwxr-xr-x | api/system-current.txt | 13 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/IScoreChangeCallback.aidl | 29 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/IWifiConnectedNetworkScorer.aidl | 33 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/IWifiManager.aidl | 5 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiManager.java | 182 | ||||
| -rw-r--r-- | wifi/java/com/android/server/wifi/BaseWifiService.java | 12 | ||||
| -rw-r--r-- | wifi/tests/src/android/net/wifi/WifiManagerTest.java | 61 |
7 files changed, 335 insertions, 0 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index e532a3afab8a..b8fbc9dfda88 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6205,6 +6205,7 @@ package android.net.wifi { method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void addOnWifiUsabilityStatsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void allowAutojoin(int, boolean); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void allowAutojoinPasspoint(@NonNull String, boolean); + method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void clearWifiConnectedNetworkScorer(); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void connect(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void connect(int, @Nullable android.net.wifi.WifiManager.ActionListener); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void disable(int, @Nullable android.net.wifi.WifiManager.ActionListener); @@ -6249,6 +6250,7 @@ package android.net.wifi { method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setMacRandomizationSettingPasspointEnabled(@NonNull String, boolean); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public boolean setSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration); method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration); + method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public boolean setWifiConnectedNetworkScorer(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.WifiConnectedNetworkScorer); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeInitiator(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startLocalOnlyHotspot(@NonNull android.net.wifi.SoftApConfiguration, @Nullable java.util.concurrent.Executor, @Nullable android.net.wifi.WifiManager.LocalOnlyHotspotCallback); @@ -6338,6 +6340,11 @@ package android.net.wifi { method public void onWifiUsabilityStats(int, boolean, @NonNull android.net.wifi.WifiUsabilityStatsEntry); } + public static interface WifiManager.ScoreChangeCallback { + method public void onStatusChange(int, boolean); + method public void onTriggerUpdateOfWifiUsabilityStats(int); + } + public static interface WifiManager.SoftApCallback { method public default void onBlockedClientConnecting(@NonNull android.net.wifi.WifiClient, int); method public default void onCapabilityChanged(@NonNull android.net.wifi.SoftApCapability); @@ -6354,6 +6361,12 @@ package android.net.wifi { field public static final int DATA_ACTIVITY_OUT = 2; // 0x2 } + public static interface WifiManager.WifiConnectedNetworkScorer { + method public void setScoreChangeCallback(@NonNull android.net.wifi.WifiManager.ScoreChangeCallback); + method public void start(int); + method public void stop(int); + } + public class WifiNetworkConnectionStatistics implements android.os.Parcelable { ctor public WifiNetworkConnectionStatistics(int, int); ctor public WifiNetworkConnectionStatistics(); diff --git a/wifi/java/android/net/wifi/IScoreChangeCallback.aidl b/wifi/java/android/net/wifi/IScoreChangeCallback.aidl new file mode 100644 index 000000000000..fd236107bc6e --- /dev/null +++ b/wifi/java/android/net/wifi/IScoreChangeCallback.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 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 android.net.wifi; + +/** + * Interface for Wi-Fi network score callback. + * + * @hide + */ +oneway interface IScoreChangeCallback +{ + void onStatusChange(int sessionId, boolean exiting); + + void onTriggerUpdateOfWifiUsabilityStats(int sessionId); +} diff --git a/wifi/java/android/net/wifi/IWifiConnectedNetworkScorer.aidl b/wifi/java/android/net/wifi/IWifiConnectedNetworkScorer.aidl new file mode 100644 index 000000000000..d9a3b0109a09 --- /dev/null +++ b/wifi/java/android/net/wifi/IWifiConnectedNetworkScorer.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2020 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 android.net.wifi; + +import android.net.wifi.IScoreChangeCallback; + +/** + * Interface for Wi-Fi connected network scorer. + * + * @hide + */ +oneway interface IWifiConnectedNetworkScorer +{ + void start(int sessionId); + + void stop(int sessionId); + + void setScoreChangeCallback(IScoreChangeCallback cbImpl); +} diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 67f166327b56..5a98ac86e783 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -35,6 +35,7 @@ import android.net.wifi.ISoftApCallback; import android.net.wifi.ISuggestionConnectionStatusListener; import android.net.wifi.ITrafficStateCallback; import android.net.wifi.ITxPacketCountListener; +import android.net.wifi.IWifiConnectedNetworkScorer; import android.net.wifi.ScanResult; import android.net.wifi.SoftApConfiguration; import android.net.wifi.WifiConfiguration; @@ -254,4 +255,8 @@ interface IWifiManager int calculateSignalLevel(int rssi); List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(in List<ScanResult> scanResults); + + boolean setWifiConnectedNetworkScorer(in IBinder binder, in IWifiConnectedNetworkScorer scorer); + + void clearWifiConnectedNetworkScorer(); } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index ec3de43ee85a..64d4eafe71bf 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -5806,4 +5806,186 @@ public class WifiManager { return new SparseArray<>(); } } + + /** + * Callback interface for framework to receive network status changes and trigger of updating + * {@link WifiUsabilityStatsEntry}. + * + * @hide + */ + @SystemApi + public interface ScoreChangeCallback { + /** + * Called by applications to indicate network status. + * + * @param sessionId The ID to indicate current Wi-Fi network connection obtained from + * {@link WifiConnectedNetworkScorer#start(int)}. + * @param isUsable The bit to indicate whether current Wi-Fi network is usable or not. + * Populated by connected network scorer in applications. + */ + void onStatusChange(int sessionId, boolean isUsable); + + /** + * Called by applications to trigger an update of {@link WifiUsabilityStatsEntry}. + * To receive update applications need to add WifiUsabilityStatsEntry listener. See + * {@link addOnWifiUsabilityStatsListener(Executor, OnWifiUsabilityStatsListener)}. + * + * @param sessionId The ID to indicate current Wi-Fi network connection obtained from + * {@link WifiConnectedNetworkScorer#start(int)}. + */ + void onTriggerUpdateOfWifiUsabilityStats(int sessionId); + } + + /** + * Callback proxy for {@link ScoreChangeCallback} objects. + * + * @hide + */ + private class ScoreChangeCallbackProxy implements ScoreChangeCallback { + private final IScoreChangeCallback mScoreChangeCallback; + + private ScoreChangeCallbackProxy(IScoreChangeCallback callback) { + mScoreChangeCallback = callback; + } + + @Override + public void onStatusChange(int sessionId, boolean isUsable) { + try { + mScoreChangeCallback.onStatusChange(sessionId, isUsable); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + @Override + public void onTriggerUpdateOfWifiUsabilityStats(int sessionId) { + try { + mScoreChangeCallback.onTriggerUpdateOfWifiUsabilityStats(sessionId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Interface for Wi-Fi connected network scorer. Should be implemented by applications and set + * when calling + * {@link WifiManager#setWifiConnectedNetworkScorer(Executor, WifiConnectedNetworkScorer)}. + * + * @hide + */ + @SystemApi + public interface WifiConnectedNetworkScorer { + /** + * Called by framework to indicate the start of a network connection. + * @param sessionId The ID to indicate current Wi-Fi network connection. + */ + void start(int sessionId); + + /** + * Called by framework to indicate the end of a network connection. + * @param sessionId The ID to indicate current Wi-Fi network connection obtained from + * {@link WifiConnectedNetworkScorer#start(int)}. + */ + void stop(int sessionId); + + /** + * Framework sets callback for score change events after application sets its scorer. + * @param cbImpl The instance for {@link WifiManager#ScoreChangeCallback}. Should be + * implemented and instantiated by framework. + */ + void setScoreChangeCallback(@NonNull ScoreChangeCallback cbImpl); + } + + /** + * Callback proxy for {@link WifiConnectedNetworkScorer} objects. + * + * @hide + */ + private class WifiConnectedNetworkScorerProxy extends IWifiConnectedNetworkScorer.Stub { + private Executor mExecutor; + private WifiConnectedNetworkScorer mScorer; + + WifiConnectedNetworkScorerProxy(Executor executor, WifiConnectedNetworkScorer scorer) { + mExecutor = executor; + mScorer = scorer; + } + + @Override + public void start(int sessionId) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "WifiConnectedNetworkScorer: " + "start: sessionId=" + sessionId); + } + Binder.clearCallingIdentity(); + mExecutor.execute(() -> mScorer.start(sessionId)); + } + + @Override + public void stop(int sessionId) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "WifiConnectedNetworkScorer: " + "stop: sessionId=" + sessionId); + } + Binder.clearCallingIdentity(); + mExecutor.execute(() -> mScorer.stop(sessionId)); + } + + @Override + public void setScoreChangeCallback(IScoreChangeCallback cbImpl) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "WifiConnectedNetworkScorer: " + + "setScoreChangeCallback: cbImpl=" + cbImpl); + } + Binder.clearCallingIdentity(); + mExecutor.execute(() -> mScorer.setScoreChangeCallback( + new ScoreChangeCallbackProxy(cbImpl))); + } + } + + /** + * Set a callback for Wi-Fi connected network scorer. See {@link WifiConnectedNetworkScorer}. + * Only a single scorer can be set. Caller will be invoked periodically by framework to inform + * client about start and stop of Wi-Fi connection. Caller can clear a previously set scorer + * using {@link clearWifiConnectedNetworkScorer()}. + * + * @param executor The executor on which callback will be invoked. + * @param scorer Scorer for Wi-Fi network implemented by application. + * @return true Scorer is set successfully. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) + public boolean setWifiConnectedNetworkScorer(@NonNull @CallbackExecutor Executor executor, + @NonNull WifiConnectedNetworkScorer scorer) { + if (executor == null) throw new IllegalArgumentException("executor cannot be null"); + if (scorer == null) throw new IllegalArgumentException("scorer cannot be null"); + if (mVerboseLoggingEnabled) { + Log.v(TAG, "setWifiConnectedNetworkScorer: scorer=" + scorer); + } + try { + return mService.setWifiConnectedNetworkScorer(new Binder(), + new WifiConnectedNetworkScorerProxy(executor, scorer)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Allow caller to clear a previously set scorer. After calling this method, + * client will no longer receive information about start and stop of Wi-Fi connection. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) + public void clearWifiConnectedNetworkScorer() { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "clearWifiConnectedNetworkScorer"); + } + try { + mService.clearWifiConnectedNetworkScorer(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java index 1cf3825d2397..08822e2762f6 100644 --- a/wifi/java/com/android/server/wifi/BaseWifiService.java +++ b/wifi/java/com/android/server/wifi/BaseWifiService.java @@ -32,6 +32,7 @@ import android.net.wifi.ISoftApCallback; import android.net.wifi.ISuggestionConnectionStatusListener; import android.net.wifi.ITrafficStateCallback; import android.net.wifi.ITxPacketCountListener; +import android.net.wifi.IWifiConnectedNetworkScorer; import android.net.wifi.IWifiManager; import android.net.wifi.ScanResult; import android.net.wifi.SoftApConfiguration; @@ -600,4 +601,15 @@ public class BaseWifiService extends IWifiManager.Stub { List<ScanResult> scanResults) { throw new UnsupportedOperationException(); } + + @Override + public boolean setWifiConnectedNetworkScorer(IBinder binder, + IWifiConnectedNetworkScorer scorer) { + throw new UnsupportedOperationException(); + } + + @Override + public void clearWifiConnectedNetworkScorer() { + throw new UnsupportedOperationException(); + } } diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java index 983ac8216124..1ee5374aaa69 100644 --- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java +++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java @@ -82,6 +82,7 @@ import android.net.wifi.WifiManager.ScanResultsCallback; import android.net.wifi.WifiManager.SoftApCallback; import android.net.wifi.WifiManager.SuggestionConnectionStatusListener; import android.net.wifi.WifiManager.TrafficStateCallback; +import android.net.wifi.WifiManager.WifiConnectedNetworkScorer; import android.os.Binder; import android.os.Build; import android.os.Handler; @@ -138,6 +139,7 @@ public class WifiManagerTest { @Mock Executor mExecutor; @Mock Executor mAnotherExecutor; @Mock ActivityManager mActivityManager; + @Mock WifiConnectedNetworkScorer mWifiConnectedNetworkScorer; private Handler mHandler; private TestLooper mLooper; @@ -2230,4 +2232,63 @@ public class WifiManagerTest { assertEquals(testResults, mWifiManager .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(new ArrayList<>())); } + + /** + * Verify the call to setWifiConnectedNetworkScorer goes to WifiServiceImpl. + */ + @Test + public void setWifiConnectedNetworkScorerGoesToWifiServiceImpl() throws Exception { + mExecutor = new SynchronousExecutor(); + mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer); + verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class), + any(IWifiConnectedNetworkScorer.Stub.class)); + } + + /** + * Verify the call to clearWifiConnectedNetworkScorer goes to WifiServiceImpl. + */ + @Test + public void clearWifiConnectedNetworkScorerGoesToWifiServiceImpl() throws Exception { + mExecutor = new SynchronousExecutor(); + mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer); + verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class), + any(IWifiConnectedNetworkScorer.Stub.class)); + + mWifiManager.clearWifiConnectedNetworkScorer(); + verify(mWifiService).clearWifiConnectedNetworkScorer(); + } + + /** + * Verify that Wi-Fi connected scorer receives score change callback after registeration. + */ + @Test + public void verifyScorerReceiveScoreChangeCallbackAfterRegistration() throws Exception { + mExecutor = new SynchronousExecutor(); + mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer); + ArgumentCaptor<IWifiConnectedNetworkScorer.Stub> scorerCaptor = + ArgumentCaptor.forClass(IWifiConnectedNetworkScorer.Stub.class); + verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class), + scorerCaptor.capture()); + scorerCaptor.getValue().setScoreChangeCallback(any()); + mLooper.dispatchAll(); + verify(mWifiConnectedNetworkScorer).setScoreChangeCallback(any()); + } + + /** + * Verify that Wi-Fi connected scorer receives session ID when start/stop methods are called. + */ + @Test + public void verifyScorerReceiveSessionIdWhenStartStopIsCalled() throws Exception { + mExecutor = new SynchronousExecutor(); + mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer); + ArgumentCaptor<IWifiConnectedNetworkScorer.Stub> callbackCaptor = + ArgumentCaptor.forClass(IWifiConnectedNetworkScorer.Stub.class); + verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class), + callbackCaptor.capture()); + callbackCaptor.getValue().start(0); + callbackCaptor.getValue().stop(10); + mLooper.dispatchAll(); + verify(mWifiConnectedNetworkScorer).start(0); + verify(mWifiConnectedNetworkScorer).stop(10); + } } |