Merge "Send offload status changed callback" into rvc-dev
This commit is contained in:
@@ -35,4 +35,5 @@ oneway interface ITetheringEventCallback
|
||||
void onConfigurationChanged(in TetheringConfigurationParcel config);
|
||||
void onTetherStatesChanged(in TetherStatesParcel states);
|
||||
void onTetherClientsChanged(in List<TetheredClient> clients);
|
||||
void onOffloadStatusChanged(int status);
|
||||
}
|
||||
|
||||
@@ -31,4 +31,5 @@ parcelable TetheringCallbackStartedParcel {
|
||||
TetheringConfigurationParcel config;
|
||||
TetherStatesParcel states;
|
||||
List<TetheredClient> tetheredClients;
|
||||
}
|
||||
int offloadStatus;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.net;
|
||||
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
@@ -34,6 +35,8 @@ import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -172,6 +175,23 @@ public class TetheringManager {
|
||||
public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14;
|
||||
public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15;
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(flag = false, value = {
|
||||
TETHER_HARDWARE_OFFLOAD_STOPPED,
|
||||
TETHER_HARDWARE_OFFLOAD_STARTED,
|
||||
TETHER_HARDWARE_OFFLOAD_FAILED,
|
||||
})
|
||||
public @interface TetherOffloadStatus {
|
||||
}
|
||||
|
||||
/** Tethering offload status is stopped. */
|
||||
public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0;
|
||||
/** Tethering offload status is started. */
|
||||
public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1;
|
||||
/** Fail to start tethering offload. */
|
||||
public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2;
|
||||
|
||||
/**
|
||||
* Create a TetheringManager object for interacting with the tethering service.
|
||||
*
|
||||
@@ -378,6 +398,9 @@ public class TetheringManager {
|
||||
@Override
|
||||
public void onTetherClientsChanged(List<TetheredClient> clients) { }
|
||||
|
||||
@Override
|
||||
public void onOffloadStatusChanged(int status) { }
|
||||
|
||||
public void waitForStarted() {
|
||||
mWaitForCallback.block(DEFAULT_TIMEOUT_MS);
|
||||
throwIfPermissionFailure(mError);
|
||||
@@ -802,6 +825,14 @@ public class TetheringManager {
|
||||
* @param clients The new set of tethered clients; the collection is not ordered.
|
||||
*/
|
||||
public void onClientsChanged(@NonNull Collection<TetheredClient> clients) {}
|
||||
|
||||
/**
|
||||
* Called when tethering offload status changes.
|
||||
*
|
||||
* <p>This will be called immediately after the callback is registered.
|
||||
* @param status The offload status.
|
||||
*/
|
||||
public void onOffloadStatusChanged(@TetherOffloadStatus int status) {}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -925,6 +956,7 @@ public class TetheringManager {
|
||||
maybeSendTetherableIfacesChangedCallback(parcel.states);
|
||||
maybeSendTetheredIfacesChangedCallback(parcel.states);
|
||||
callback.onClientsChanged(parcel.tetheredClients);
|
||||
callback.onOffloadStatusChanged(parcel.offloadStatus);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -960,6 +992,11 @@ public class TetheringManager {
|
||||
public void onTetherClientsChanged(final List<TetheredClient> clients) {
|
||||
executor.execute(() -> callback.onClientsChanged(clients));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOffloadStatusChanged(final int status) {
|
||||
executor.execute(() -> callback.onOffloadStatusChanged(status));
|
||||
}
|
||||
};
|
||||
getConnector(c -> c.registerTetheringEventCallback(remoteCallback, callerPkg));
|
||||
mTetheringEventCallbacks.put(callback, remoteCallback);
|
||||
|
||||
@@ -44,6 +44,9 @@ import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
|
||||
import static android.net.util.TetheringMessageBase.BASE_MASTER;
|
||||
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
|
||||
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
|
||||
@@ -237,6 +240,7 @@ public class Tethering {
|
||||
private TetherStatesParcel mTetherStatesParcel;
|
||||
private boolean mDataSaverEnabled = false;
|
||||
private String mWifiP2pTetherInterface = null;
|
||||
private int mOffloadStatus = TETHER_HARDWARE_OFFLOAD_STOPPED;
|
||||
|
||||
@GuardedBy("mPublicSync")
|
||||
private EthernetManager.TetheredInterfaceRequest mEthernetIfaceRequest;
|
||||
@@ -1901,12 +1905,15 @@ public class Tethering {
|
||||
// OffloadController implementation.
|
||||
class OffloadWrapper {
|
||||
public void start() {
|
||||
mOffloadController.start();
|
||||
final int status = mOffloadController.start() ? TETHER_HARDWARE_OFFLOAD_STARTED
|
||||
: TETHER_HARDWARE_OFFLOAD_FAILED;
|
||||
updateOffloadStatus(status);
|
||||
sendOffloadExemptPrefixes();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
mOffloadController.stop();
|
||||
updateOffloadStatus(TETHER_HARDWARE_OFFLOAD_STOPPED);
|
||||
}
|
||||
|
||||
public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
|
||||
@@ -1967,6 +1974,13 @@ public class Tethering {
|
||||
|
||||
mOffloadController.setLocalPrefixes(localPrefixes);
|
||||
}
|
||||
|
||||
private void updateOffloadStatus(final int newStatus) {
|
||||
if (newStatus == mOffloadStatus) return;
|
||||
|
||||
mOffloadStatus = newStatus;
|
||||
reportOffloadStatusChanged(mOffloadStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2001,6 +2015,7 @@ public class Tethering {
|
||||
parcel.tetheredClients = hasListPermission
|
||||
? mConnectedClientsTracker.getLastTetheredClients()
|
||||
: Collections.emptyList();
|
||||
parcel.offloadStatus = mOffloadStatus;
|
||||
try {
|
||||
callback.onCallbackStarted(parcel);
|
||||
} catch (RemoteException e) {
|
||||
@@ -2095,6 +2110,21 @@ public class Tethering {
|
||||
}
|
||||
}
|
||||
|
||||
private void reportOffloadStatusChanged(final int status) {
|
||||
final int length = mTetheringEventCallbacks.beginBroadcast();
|
||||
try {
|
||||
for (int i = 0; i < length; i++) {
|
||||
try {
|
||||
mTetheringEventCallbacks.getBroadcastItem(i).onOffloadStatusChanged(status);
|
||||
} catch (RemoteException e) {
|
||||
// Not really very much to do here.
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
mTetheringEventCallbacks.finishBroadcast();
|
||||
}
|
||||
}
|
||||
|
||||
void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {
|
||||
// Binder.java closes the resource for us.
|
||||
@SuppressWarnings("resource")
|
||||
|
||||
@@ -34,6 +34,9 @@ import static android.net.TetheringManager.TETHERING_USB;
|
||||
import static android.net.TetheringManager.TETHERING_WIFI;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
|
||||
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
|
||||
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
|
||||
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
|
||||
@@ -169,6 +172,7 @@ public class TetheringTest {
|
||||
@Mock private Context mContext;
|
||||
@Mock private NetworkStatsManager mStatsManager;
|
||||
@Mock private OffloadHardwareInterface mOffloadHardwareInterface;
|
||||
@Mock private OffloadHardwareInterface.ForwardedStats mForwardedStats;
|
||||
@Mock private Resources mResources;
|
||||
@Mock private TelephonyManager mTelephonyManager;
|
||||
@Mock private UsbManager mUsbManager;
|
||||
@@ -463,6 +467,9 @@ public class TetheringTest {
|
||||
mInterfaceConfiguration.flags = new String[0];
|
||||
when(mRouterAdvertisementDaemon.start())
|
||||
.thenReturn(true);
|
||||
initOffloadConfiguration(true /* offloadConfig */, true /* offloadControl */,
|
||||
0 /* defaultDisabled */);
|
||||
when(mOffloadHardwareInterface.getForwardedStats(any())).thenReturn(mForwardedStats);
|
||||
|
||||
mServiceContext = new TestContext(mContext);
|
||||
when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(null);
|
||||
@@ -1136,6 +1143,7 @@ public class TetheringTest {
|
||||
private final ArrayList<TetheringConfigurationParcel> mTetheringConfigs =
|
||||
new ArrayList<>();
|
||||
private final ArrayList<TetherStatesParcel> mTetherStates = new ArrayList<>();
|
||||
private final ArrayList<Integer> mOffloadStatus = new ArrayList<>();
|
||||
|
||||
// This function will remove the recorded callbacks, so it must be called once for
|
||||
// each callback. If this is called after multiple callback, the order matters.
|
||||
@@ -1171,6 +1179,11 @@ public class TetheringTest {
|
||||
assertNoConfigChangeCallback();
|
||||
}
|
||||
|
||||
public void expectOffloadStatusChanged(final int expectedStatus) {
|
||||
assertOffloadStatusChangedCallback();
|
||||
assertEquals(mOffloadStatus.remove(0), new Integer(expectedStatus));
|
||||
}
|
||||
|
||||
public TetherStatesParcel pollTetherStatesChanged() {
|
||||
assertStateChangeCallback();
|
||||
return mTetherStates.remove(0);
|
||||
@@ -1196,11 +1209,17 @@ public class TetheringTest {
|
||||
// TODO: check this
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOffloadStatusChanged(final int status) {
|
||||
mOffloadStatus.add(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
|
||||
mActualUpstreams.add(parcel.upstreamNetwork);
|
||||
mTetheringConfigs.add(parcel.config);
|
||||
mTetherStates.add(parcel.states);
|
||||
mOffloadStatus.add(parcel.offloadStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1222,6 +1241,10 @@ public class TetheringTest {
|
||||
assertFalse(mTetherStates.isEmpty());
|
||||
}
|
||||
|
||||
public void assertOffloadStatusChangedCallback() {
|
||||
assertFalse(mOffloadStatus.isEmpty());
|
||||
}
|
||||
|
||||
public void assertNoCallback() {
|
||||
assertNoUpstreamChangeCallback();
|
||||
assertNoConfigChangeCallback();
|
||||
@@ -1270,6 +1293,7 @@ public class TetheringTest {
|
||||
mTethering.getTetheringConfiguration().toStableParcelable());
|
||||
TetherStatesParcel tetherState = callback.pollTetherStatesChanged();
|
||||
assertTetherStatesNotNullButEmpty(tetherState);
|
||||
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
|
||||
// 2. Enable wifi tethering.
|
||||
UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
|
||||
when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
|
||||
@@ -1287,6 +1311,7 @@ public class TetheringTest {
|
||||
tetherState = callback.pollTetherStatesChanged();
|
||||
assertArrayEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
|
||||
callback.expectUpstreamChanged(upstreamState.network);
|
||||
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STARTED);
|
||||
|
||||
// 3. Register second callback.
|
||||
mTethering.registerTetheringEventCallback(callback2);
|
||||
@@ -1296,6 +1321,7 @@ public class TetheringTest {
|
||||
mTethering.getTetheringConfiguration().toStableParcelable());
|
||||
tetherState = callback2.pollTetherStatesChanged();
|
||||
assertEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
|
||||
callback2.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STARTED);
|
||||
|
||||
// 4. Unregister first callback and disable wifi tethering
|
||||
mTethering.unregisterTetheringEventCallback(callback);
|
||||
@@ -1307,9 +1333,58 @@ public class TetheringTest {
|
||||
assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
|
||||
mLooper.dispatchAll();
|
||||
callback2.expectUpstreamChanged(new Network[] {null});
|
||||
callback2.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
|
||||
callback.assertNoCallback();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReportFailCallbackIfOffloadNotSupported() throws Exception {
|
||||
final UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
|
||||
TestTetheringEventCallback callback = new TestTetheringEventCallback();
|
||||
mTethering.registerTetheringEventCallback(callback);
|
||||
mLooper.dispatchAll();
|
||||
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
|
||||
|
||||
// 1. Offload fail if no OffloadConfig.
|
||||
initOffloadConfiguration(false /* offloadConfig */, true /* offloadControl */,
|
||||
0 /* defaultDisabled */);
|
||||
runUsbTethering(upstreamState);
|
||||
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED);
|
||||
runStopUSBTethering();
|
||||
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
|
||||
reset(mUsbManager);
|
||||
// 2. Offload fail if no OffloadControl.
|
||||
initOffloadConfiguration(true /* offloadConfig */, false /* offloadControl */,
|
||||
0 /* defaultDisabled */);
|
||||
runUsbTethering(upstreamState);
|
||||
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED);
|
||||
runStopUSBTethering();
|
||||
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
|
||||
reset(mUsbManager);
|
||||
// 3. Offload fail if disabled by settings.
|
||||
initOffloadConfiguration(true /* offloadConfig */, true /* offloadControl */,
|
||||
1 /* defaultDisabled */);
|
||||
runUsbTethering(upstreamState);
|
||||
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED);
|
||||
runStopUSBTethering();
|
||||
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
|
||||
}
|
||||
|
||||
private void runStopUSBTethering() {
|
||||
mTethering.stopTethering(TETHERING_USB);
|
||||
mLooper.dispatchAll();
|
||||
mTethering.interfaceRemoved(TEST_USB_IFNAME);
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
|
||||
private void initOffloadConfiguration(final boolean offloadConfig,
|
||||
final boolean offloadControl, final int defaultDisabled) {
|
||||
when(mOffloadHardwareInterface.initOffloadConfig()).thenReturn(offloadConfig);
|
||||
when(mOffloadHardwareInterface.initOffloadControl(any())).thenReturn(offloadControl);
|
||||
when(mOffloadHardwareInterface.getDefaultTetherOffloadDisabled()).thenReturn(
|
||||
defaultDisabled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiSimAware() throws Exception {
|
||||
final TetheringConfiguration initailConfig = mTethering.getTetheringConfiguration();
|
||||
|
||||
Reference in New Issue
Block a user