Extension API: Create System APIs to allow OEM module to override WiFi

scorer in AOSP

Create WiFi scorer interface and score change callback interface in WifiManager; Define register and unregister methods for WiFi scorer.

Test: atest android.net.wifi
Bug: 135573686, 122133502, 136312816, 135572156

Change-Id: Ib51d877a463d1f69b31b9743917ea1b3590a30f7
Signed-off-by: Mingguang Xu <mingguangxu@google.com>
This commit is contained in:
Mingguang Xu
2019-12-20 16:11:07 -08:00
parent 3662019068
commit ec6f8ce6fd
7 changed files with 335 additions and 0 deletions

View File

@@ -6132,6 +6132,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);
@@ -6175,6 +6176,7 @@ package android.net.wifi {
method @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) public void setDeviceMobilityState(int);
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);
@@ -6264,6 +6266,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);
@@ -6280,6 +6287,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();

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
@@ -252,4 +253,8 @@ interface IWifiManager
int calculateSignalLevel(int rssi);
List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(in List<ScanResult> scanResults);
boolean setWifiConnectedNetworkScorer(in IBinder binder, in IWifiConnectedNetworkScorer scorer);
void clearWifiConnectedNetworkScorer();
}

View File

@@ -5777,4 +5777,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();
}
}
}

View File

@@ -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;
@@ -595,4 +596,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();
}
}

View File

@@ -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;
@@ -2219,4 +2221,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);
}
}