Merge "Remove WRITE_SETTINGS permission from Tethering APIs" into main
This commit is contained in:
commit
915d138309
10 changed files with 157 additions and 52 deletions
|
|
@ -63,6 +63,7 @@ java_defaults {
|
|||
static_libs: [
|
||||
"androidx.annotation_annotation",
|
||||
"connectivity-net-module-utils-bpf",
|
||||
"com.android.net.flags-aconfig-java",
|
||||
"modules-utils-build",
|
||||
"modules-utils-statemachine",
|
||||
"networkstack-client",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ package android.net {
|
|||
method public boolean isTetheringSupported(@NonNull String);
|
||||
method public void requestLatestTetheringEntitlementResult(int, @NonNull android.os.ResultReceiver, boolean);
|
||||
method @Deprecated public int setUsbTethering(boolean);
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
|
||||
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
|
||||
method @Deprecated public int tether(@NonNull String);
|
||||
method @Deprecated public int untether(@NonNull String);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ package android.net {
|
|||
}
|
||||
|
||||
public class TetheringManager {
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering();
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int);
|
||||
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
|
||||
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopAllTethering();
|
||||
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
|
||||
field @Deprecated public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
|
||||
field public static final int CONNECTIVITY_SCOPE_LOCAL = 2; // 0x2
|
||||
field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
|
||||
|
|
|
|||
|
|
@ -1300,18 +1300,12 @@ public class TetheringManager {
|
|||
* Starts tethering and runs tether provisioning for the given type if needed. If provisioning
|
||||
* fails, stopTethering will be called automatically.
|
||||
*
|
||||
* <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
|
||||
* fail if a tethering entitlement check is required.
|
||||
*
|
||||
* @param type The tethering type, on of the {@code TetheringManager#TETHERING_*} constants.
|
||||
* @param executor {@link Executor} to specify the thread upon which the callback of
|
||||
* TetheringRequest will be invoked.
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(anyOf = {
|
||||
android.Manifest.permission.TETHER_PRIVILEGED,
|
||||
android.Manifest.permission.WRITE_SETTINGS
|
||||
})
|
||||
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public void startTethering(int type, @NonNull final Executor executor,
|
||||
@NonNull final StartTetheringCallback callback) {
|
||||
|
|
@ -1322,14 +1316,9 @@ public class TetheringManager {
|
|||
* Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
|
||||
* applicable.
|
||||
*
|
||||
* <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
|
||||
* fail if a tethering entitlement check is required.
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(anyOf = {
|
||||
android.Manifest.permission.TETHER_PRIVILEGED,
|
||||
android.Manifest.permission.WRITE_SETTINGS
|
||||
})
|
||||
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
|
||||
@SystemApi
|
||||
public void stopTethering(@TetheringType final int type) {
|
||||
final String callerPkg = mContext.getOpPackageName();
|
||||
|
|
@ -1384,9 +1373,6 @@ public class TetheringManager {
|
|||
* {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN} will be returned. If {@code showEntitlementUi} is
|
||||
* true, entitlement will be run.
|
||||
*
|
||||
* <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
|
||||
* fail if a tethering entitlement check is required.
|
||||
*
|
||||
* @param type the downstream type of tethering. Must be one of {@code #TETHERING_*} constants.
|
||||
* @param showEntitlementUi a boolean indicating whether to check result for the UI-based
|
||||
* entitlement check or the silent entitlement check.
|
||||
|
|
@ -1397,10 +1383,7 @@ public class TetheringManager {
|
|||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(anyOf = {
|
||||
android.Manifest.permission.TETHER_PRIVILEGED,
|
||||
android.Manifest.permission.WRITE_SETTINGS
|
||||
})
|
||||
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
|
||||
public void requestLatestTetheringEntitlementResult(@TetheringType int type,
|
||||
boolean showEntitlementUi,
|
||||
@NonNull Executor executor,
|
||||
|
|
@ -2083,10 +2066,7 @@ public class TetheringManager {
|
|||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(anyOf = {
|
||||
android.Manifest.permission.TETHER_PRIVILEGED,
|
||||
android.Manifest.permission.WRITE_SETTINGS
|
||||
})
|
||||
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
|
||||
public void stopAllTethering() {
|
||||
final String callerPkg = mContext.getOpPackageName();
|
||||
Log.i(TAG, "stopAllTethering caller:" + callerPkg);
|
||||
|
|
|
|||
|
|
@ -451,6 +451,10 @@ public class Tethering {
|
|||
return mSettingsObserver;
|
||||
}
|
||||
|
||||
boolean isTetheringWithSoftApConfigEnabled() {
|
||||
return mDeps.isTetheringWithSoftApConfigEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start to register callbacks.
|
||||
* Call this function when tethering is ready to handle callback events.
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.android.modules.utils.build.SdkLevel;
|
||||
import com.android.net.flags.Flags;
|
||||
import com.android.net.module.util.RoutingCoordinatorManager;
|
||||
import com.android.net.module.util.RoutingCoordinatorService;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
|
|
@ -208,4 +209,12 @@ public abstract class TetheringDependencies {
|
|||
public int getBinderCallingUid() {
|
||||
return Binder.getCallingUid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for tethering_with_soft_ap_config feature flag.
|
||||
*/
|
||||
public boolean isTetheringWithSoftApConfigEnabled() {
|
||||
return Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM
|
||||
&& Flags.tetheringWithSoftApConfig();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -310,6 +310,10 @@ public class TetheringService extends Service {
|
|||
|
||||
if (hasTetherPrivilegedPermission()) return true;
|
||||
|
||||
// After TetheringManager moves to public API, prevent third-party apps from being able
|
||||
// to change tethering with only WRITE_SETTINGS permission.
|
||||
if (mTethering.isTetheringWithSoftApConfigEnabled()) return false;
|
||||
|
||||
if (mTethering.isTetherProvisioningRequired()) return false;
|
||||
|
||||
int uid = getBinderCallingUid();
|
||||
|
|
|
|||
|
|
@ -154,31 +154,43 @@ public final class TetheringServiceTest {
|
|||
}
|
||||
|
||||
private void runAsNoPermission(final TestTetheringCall test) throws Exception {
|
||||
runTetheringCall(test, true /* isTetheringAllowed */, new String[0]);
|
||||
runTetheringCall(test, true /* isTetheringAllowed */, false /* isWriteSettingsAllowed */,
|
||||
new String[0]);
|
||||
}
|
||||
|
||||
private void runAsTetherPrivileged(final TestTetheringCall test) throws Exception {
|
||||
runTetheringCall(test, true /* isTetheringAllowed */, TETHER_PRIVILEGED);
|
||||
runTetheringCall(test, true /* isTetheringAllowed */, false /* isWriteSettingsAllowed */,
|
||||
TETHER_PRIVILEGED);
|
||||
}
|
||||
|
||||
private void runAsAccessNetworkState(final TestTetheringCall test) throws Exception {
|
||||
runTetheringCall(test, true /* isTetheringAllowed */, ACCESS_NETWORK_STATE);
|
||||
runTetheringCall(test, true /* isTetheringAllowed */, false /* isWriteSettingsAllowed */,
|
||||
ACCESS_NETWORK_STATE);
|
||||
}
|
||||
|
||||
private void runAsWriteSettings(final TestTetheringCall test) throws Exception {
|
||||
runTetheringCall(test, true /* isTetheringAllowed */, WRITE_SETTINGS);
|
||||
runTetheringCall(test, true /* isTetheringAllowed */, false /* isWriteSettingsAllowed */,
|
||||
WRITE_SETTINGS);
|
||||
}
|
||||
|
||||
private void runAsWriteSettingsWhenWriteSettingsAllowed(
|
||||
final TestTetheringCall test) throws Exception {
|
||||
runTetheringCall(test, true /* isTetheringAllowed */, true /* isWriteSettingsAllowed */,
|
||||
WRITE_SETTINGS);
|
||||
}
|
||||
|
||||
private void runAsTetheringDisallowed(final TestTetheringCall test) throws Exception {
|
||||
runTetheringCall(test, false /* isTetheringAllowed */, TETHER_PRIVILEGED);
|
||||
runTetheringCall(test, false /* isTetheringAllowed */, false /* isWriteSettingsAllowed */,
|
||||
TETHER_PRIVILEGED);
|
||||
}
|
||||
|
||||
private void runAsNetworkSettings(final TestTetheringCall test) throws Exception {
|
||||
runTetheringCall(test, true /* isTetheringAllowed */, NETWORK_SETTINGS, TETHER_PRIVILEGED);
|
||||
runTetheringCall(test, true /* isTetheringAllowed */, false /* isWriteSettingsAllowed */,
|
||||
NETWORK_SETTINGS, TETHER_PRIVILEGED);
|
||||
}
|
||||
|
||||
private void runTetheringCall(final TestTetheringCall test, boolean isTetheringAllowed,
|
||||
String... permissions) throws Exception {
|
||||
boolean isWriteSettingsAllowed, String... permissions) throws Exception {
|
||||
// Allow the test to run even if ACCESS_NETWORK_STATE was granted at the APK level
|
||||
if (!CollectionUtils.contains(permissions, ACCESS_NETWORK_STATE)) {
|
||||
mMockConnector.setPermission(ACCESS_NETWORK_STATE, PERMISSION_DENIED);
|
||||
|
|
@ -188,6 +200,8 @@ public final class TetheringServiceTest {
|
|||
try {
|
||||
when(mTethering.isTetheringSupported()).thenReturn(true);
|
||||
when(mTethering.isTetheringAllowed()).thenReturn(isTetheringAllowed);
|
||||
when(mTethering.isTetheringWithSoftApConfigEnabled())
|
||||
.thenReturn(!isWriteSettingsAllowed);
|
||||
test.runTetheringCall(new TestTetheringResult());
|
||||
} finally {
|
||||
mUiAutomation.dropShellPermissionIdentity();
|
||||
|
|
@ -213,7 +227,7 @@ public final class TetheringServiceTest {
|
|||
runAsNoPermission((result) -> {
|
||||
mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
|
||||
result);
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -224,7 +238,16 @@ public final class TetheringServiceTest {
|
|||
});
|
||||
|
||||
runAsWriteSettings((result) -> {
|
||||
mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
|
||||
result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
||||
runAsWriteSettingsWhenWriteSettingsAllowed((result) -> {
|
||||
runTether(result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -252,7 +275,7 @@ public final class TetheringServiceTest {
|
|||
runAsNoPermission((result) -> {
|
||||
mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
|
||||
result);
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -263,7 +286,16 @@ public final class TetheringServiceTest {
|
|||
});
|
||||
|
||||
runAsWriteSettings((result) -> {
|
||||
mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
|
||||
result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
||||
runAsWriteSettingsWhenWriteSettingsAllowed((result) -> {
|
||||
runUnTether(result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -297,7 +329,7 @@ public final class TetheringServiceTest {
|
|||
runAsNoPermission((result) -> {
|
||||
mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG,
|
||||
TEST_ATTRIBUTION_TAG, result);
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -308,7 +340,16 @@ public final class TetheringServiceTest {
|
|||
});
|
||||
|
||||
runAsWriteSettings((result) -> {
|
||||
mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG,
|
||||
TEST_ATTRIBUTION_TAG, result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
||||
runAsWriteSettingsWhenWriteSettingsAllowed((result) -> {
|
||||
runSetUsbTethering(result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -341,7 +382,7 @@ public final class TetheringServiceTest {
|
|||
runAsNoPermission((result) -> {
|
||||
mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
|
||||
result);
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -361,7 +402,16 @@ public final class TetheringServiceTest {
|
|||
});
|
||||
|
||||
runAsWriteSettings((result) -> {
|
||||
mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
|
||||
result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
||||
runAsWriteSettingsWhenWriteSettingsAllowed((result) -> {
|
||||
runStartTethering(result, request);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -446,7 +496,7 @@ public final class TetheringServiceTest {
|
|||
runAsNoPermission((result) -> {
|
||||
mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG,
|
||||
TEST_ATTRIBUTION_TAG, result);
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -457,7 +507,16 @@ public final class TetheringServiceTest {
|
|||
});
|
||||
|
||||
runAsWriteSettings((result) -> {
|
||||
mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG,
|
||||
TEST_ATTRIBUTION_TAG, result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
||||
runAsWriteSettingsWhenWriteSettingsAllowed((result) -> {
|
||||
runStopTethering(result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -486,11 +545,13 @@ public final class TetheringServiceTest {
|
|||
public void testRequestLatestTetheringEntitlementResult() throws Exception {
|
||||
// Run as no permission.
|
||||
final MyResultReceiver result = new MyResultReceiver(null);
|
||||
mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
|
||||
true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG);
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractions(mTethering);
|
||||
runAsNoPermission((none) -> {
|
||||
mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
|
||||
true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
||||
runAsTetherPrivileged((none) -> {
|
||||
runRequestLatestTetheringEntitlementResult();
|
||||
|
|
@ -501,22 +562,30 @@ public final class TetheringServiceTest {
|
|||
mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
|
||||
true /* showEntitlementUi */, TEST_WRONG_PACKAGE, TEST_ATTRIBUTION_TAG);
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractions(mTethering);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
||||
runAsWriteSettings((none) -> {
|
||||
mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
|
||||
true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
||||
runAsWriteSettingsWhenWriteSettingsAllowed((none) -> {
|
||||
runRequestLatestTetheringEntitlementResult();
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
||||
runAsTetheringDisallowed((none) -> {
|
||||
final MyResultReceiver receiver = new MyResultReceiver(null);
|
||||
mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, receiver,
|
||||
mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
|
||||
true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG);
|
||||
verify(mTethering).isTetheringSupported();
|
||||
verify(mTethering).isTetheringAllowed();
|
||||
receiver.assertResult(TETHER_ERROR_UNSUPPORTED);
|
||||
result.assertResult(TETHER_ERROR_UNSUPPORTED);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
}
|
||||
|
|
@ -600,7 +669,7 @@ public final class TetheringServiceTest {
|
|||
public void testStopAllTethering() throws Exception {
|
||||
runAsNoPermission((result) -> {
|
||||
mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -611,7 +680,15 @@ public final class TetheringServiceTest {
|
|||
});
|
||||
|
||||
runAsWriteSettings((result) -> {
|
||||
mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
||||
runAsWriteSettingsWhenWriteSettingsAllowed((result) -> {
|
||||
runStopAllTethering(result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -637,7 +714,7 @@ public final class TetheringServiceTest {
|
|||
runAsNoPermission((result) -> {
|
||||
mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
|
||||
result);
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
@ -648,7 +725,16 @@ public final class TetheringServiceTest {
|
|||
});
|
||||
|
||||
runAsWriteSettings((result) -> {
|
||||
mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
|
||||
result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
||||
runAsWriteSettingsWhenWriteSettingsAllowed((result) -> {
|
||||
runIsTetheringSupported(result);
|
||||
verify(mTethering).isTetheringWithSoftApConfigEnabled();
|
||||
verify(mTethering).isTetherProvisioningRequired();
|
||||
verifyNoMoreInteractionsForTethering();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ java_defaults {
|
|||
|
||||
static_libs: [
|
||||
"TetheringCommonTests",
|
||||
"com.android.net.flags-aconfig-java",
|
||||
"compatibility-device-util-axt",
|
||||
"cts-net-utils",
|
||||
"net-tests-utils",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ package android.tethering.test;
|
|||
|
||||
import static android.Manifest.permission.MODIFY_PHONE_STATE;
|
||||
import static android.Manifest.permission.TETHER_PRIVILEGED;
|
||||
import static android.Manifest.permission.WRITE_SETTINGS;
|
||||
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||
|
|
@ -71,6 +72,7 @@ import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
|
|||
import android.net.wifi.SoftApConfiguration;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.net.wifi.WifiSsid;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.ResultReceiver;
|
||||
|
|
@ -83,6 +85,7 @@ import androidx.test.InstrumentationRegistry;
|
|||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.modules.utils.build.SdkLevel;
|
||||
import com.android.net.flags.Flags;
|
||||
import com.android.testutils.ParcelUtils;
|
||||
|
||||
import org.junit.After;
|
||||
|
|
@ -457,12 +460,29 @@ public class TetheringManagerTest {
|
|||
} catch (UnsupportedOperationException expect) { }
|
||||
}
|
||||
|
||||
private boolean isTetheringWithSoftApConfigEnabled() {
|
||||
return Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM
|
||||
&& Flags.tetheringWithSoftApConfig();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableTetheringPermission() throws Exception {
|
||||
public void testStartTetheringNoPermission() throws Exception {
|
||||
final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
|
||||
|
||||
// No permission
|
||||
mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
|
||||
c -> c.run() /* executor */, startTetheringCallback);
|
||||
startTetheringCallback.expectTetheringFailed(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
|
||||
// WRITE_SETTINGS not sufficient
|
||||
if (isTetheringWithSoftApConfigEnabled()) {
|
||||
runAsShell(WRITE_SETTINGS, () -> {
|
||||
mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
|
||||
c -> c.run() /* executor */, startTetheringCallback);
|
||||
startTetheringCallback.expectTetheringFailed(
|
||||
TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class EntitlementResultListener implements OnTetheringEntitlementResultListener {
|
||||
|
|
|
|||
Loading…
Reference in a new issue