Merge "Send offload status changed callback" am: a24b188455 am: 1a762405b2

Change-Id: I5a963894fda3935f2f9643fc8483c3dd68112153
This commit is contained in:
Automerger Merge Worker
2020-03-09 03:28:35 +00:00
5 changed files with 146 additions and 2 deletions

View File

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

View File

@@ -31,4 +31,5 @@ parcelable TetheringCallbackStartedParcel {
TetheringConfigurationParcel config;
TetherStatesParcel states;
List<TetheredClient> tetheredClients;
}
int offloadStatus;
}

View File

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

View File

@@ -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")

View File

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