Add hostside CTS tests for SoftApConfig redaction

Add hostside CTS tests to test for SoftApConfiguration being redacted
from TetheringInterface for apps that don't own that config.

Bug: 216524590
Test: atest CtsHostsideNetworkTests
Change-Id: I823c8e94cc6fe10c6118e7a694da368e585bbd69
This commit is contained in:
Quang Anh Luong 2024-11-07 15:03:58 +09:00
commit b5b82cc424
7 changed files with 325 additions and 2 deletions

View file

@ -19,8 +19,7 @@ package {
java_test_helper_library {
name: "CtsHostsideNetworkTestsAidl",
sdk_version: "current",
min_sdk_version: "30",
sdk_version: "system_current",
srcs: [
"com/android/cts/net/hostside/*.aidl",
"com/android/cts/net/hostside/*.java",

View file

@ -0,0 +1,23 @@
/*
* Copyright (C) 2024 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 com.android.cts.net.hostside;
import android.net.TetheringInterface;
interface ITetheringHelper {
TetheringInterface getTetheredWifiInterface();
}

View file

@ -0,0 +1,88 @@
/*
* Copyright (C) 2024 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 com.android.cts.net.hostside;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.TetheringInterface;
import android.os.ConditionVariable;
import android.os.IBinder;
import android.os.RemoteException;
public class TetheringHelperClient {
private static final int TIMEOUT_MS = 5000;
private static final String PACKAGE = TetheringHelperClient.class.getPackage().getName();
private static final String APP2_PACKAGE = PACKAGE + ".app2";
private static final String SERVICE_NAME = APP2_PACKAGE + ".TetheringHelperService";
private Context mContext;
private ServiceConnection mServiceConnection;
private ITetheringHelper mService;
public TetheringHelperClient(Context context) {
mContext = context;
}
/**
* Binds to TetheringHelperService.
*/
public void bind() {
if (mService != null) {
throw new IllegalStateException("Already bound");
}
final ConditionVariable cv = new ConditionVariable();
mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = ITetheringHelper.Stub.asInterface(service);
cv.open();
}
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};
final Intent intent = new Intent();
intent.setComponent(new ComponentName(APP2_PACKAGE, SERVICE_NAME));
mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
cv.block(TIMEOUT_MS);
if (mService == null) {
throw new IllegalStateException(
"Could not bind to TetheringHelperService after " + TIMEOUT_MS + "ms");
}
}
/**
* Unbinds from TetheringHelperService.
*/
public void unbind() {
if (mService != null) {
mContext.unbindService(mServiceConnection);
}
}
/**
* Returns the tethered Wifi interface as seen from TetheringHelperService.
*/
public TetheringInterface getTetheredWifiInterface() throws RemoteException {
return mService.getTetheredWifiInterface();
}
}

View file

@ -0,0 +1,80 @@
/*
* Copyright (C) 2024 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 com.android.cts.net.hostside;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import android.content.Context;
import android.net.TetheringInterface;
import android.net.cts.util.CtsTetheringUtils;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiSsid;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.nio.charset.StandardCharsets;
public class TetheringTest {
private CtsTetheringUtils mCtsTetheringUtils;
private TetheringHelperClient mTetheringHelperClient;
@Before
public void setUp() throws Exception {
Context targetContext = getInstrumentation().getTargetContext();
mCtsTetheringUtils = new CtsTetheringUtils(targetContext);
mTetheringHelperClient = new TetheringHelperClient(targetContext);
mTetheringHelperClient.bind();
}
@After
public void tearDown() throws Exception {
mTetheringHelperClient.unbind();
}
/**
* Starts Wifi tethering and tests that the SoftApConfiguration is redacted from
* TetheringEventCallback for other apps.
*/
@Test
public void testSoftApConfigurationRedactedForOtherUids() throws Exception {
final CtsTetheringUtils.TestTetheringEventCallback tetherEventCallback =
mCtsTetheringUtils.registerTetheringEventCallback();
SoftApConfiguration softApConfig = new SoftApConfiguration.Builder()
.setWifiSsid(WifiSsid.fromBytes("This is an SSID!"
.getBytes(StandardCharsets.UTF_8))).build();
final TetheringInterface tetheringInterface =
mCtsTetheringUtils.startWifiTethering(tetherEventCallback, softApConfig);
assertNotNull(tetheringInterface);
assertEquals(softApConfig, tetheringInterface.getSoftApConfiguration());
try {
TetheringInterface tetheringInterfaceForApp2 =
mTetheringHelperClient.getTetheredWifiInterface();
assertNotNull(tetheringInterfaceForApp2);
assertNull(tetheringInterfaceForApp2.getSoftApConfiguration());
assertEquals(
tetheringInterface.getInterface(), tetheringInterfaceForApp2.getInterface());
} finally {
mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
}
}
}

View file

@ -42,6 +42,8 @@
android:debuggable="true">
<service android:name=".RemoteSocketFactoryService"
android:exported="true"/>
<service android:name=".TetheringHelperService"
android:exported="true"/>
</application>
<!--

View file

@ -0,0 +1,78 @@
/*
* Copyright (C) 2024 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 com.android.cts.net.hostside.app2;
import static android.net.TetheringManager.TETHERING_WIFI;
import android.app.Service;
import android.content.Intent;
import android.net.TetheringInterface;
import android.net.TetheringManager;
import android.os.IBinder;
import androidx.annotation.NonNull;
import com.android.cts.net.hostside.ITetheringHelper;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class TetheringHelperService extends Service {
private static final String TAG = TetheringHelperService.class.getSimpleName();
private ITetheringHelper.Stub mBinder = new ITetheringHelper.Stub() {
public TetheringInterface getTetheredWifiInterface() {
ArrayBlockingQueue<TetheringInterface> queue = new ArrayBlockingQueue<>(1);
TetheringManager.TetheringEventCallback callback =
new TetheringManager.TetheringEventCallback() {
@Override
public void onTetheredInterfacesChanged(
@NonNull Set<TetheringInterface> interfaces) {
for (TetheringInterface iface : interfaces) {
if (iface.getType() == TETHERING_WIFI) {
queue.offer(iface);
break;
}
}
}
};
TetheringManager tm =
TetheringHelperService.this.getSystemService(TetheringManager.class);
tm.registerTetheringEventCallback(Runnable::run, callback);
TetheringInterface iface;
try {
iface = queue.poll(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new IllegalStateException("Wait for wifi TetheredInterface interrupted");
} finally {
tm.unregisterTetheringEventCallback(callback);
}
if (iface == null) {
throw new IllegalStateException(
"No wifi TetheredInterface received after 5 seconds");
}
return iface;
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (C) 2024 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 com.android.cts.net;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.AfterClassWithInfo;
import com.android.tradefed.testtype.junit4.BeforeClassWithInfo;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
public class HostsideTetheringTests extends HostsideNetworkTestCase {
/**
* Set up the test once before running all the tests.
*/
@BeforeClassWithInfo
public static void setUpOnce(TestInformation testInfo) throws Exception {
uninstallPackage(testInfo, TEST_APP2_PKG, false);
installPackage(testInfo, TEST_APP2_APK);
}
/**
* Tear down the test once after running all the tests.
*/
@AfterClassWithInfo
public static void tearDownOnce(TestInformation testInfo)
throws DeviceNotAvailableException {
uninstallPackage(testInfo, TEST_APP2_PKG, true);
}
@Test
public void testSoftApConfigurationRedactedForOtherApps() throws Exception {
runDeviceTests(TEST_PKG, TEST_PKG + ".TetheringTest",
"testSoftApConfigurationRedactedForOtherUids");
}
}