blob: b5f121bd45c0376dcd64292c08f68f454fff70c2 [file] [log] [blame]
package com.android.clockwork.connectivity;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.verify;
import static org.robolectric.Shadows.shadowOf;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.os.ConditionVariable;
import android.os.UserHandle;
import android.util.DisplayMetrics;
import androidx.annotation.NonNull;
import com.android.clockwork.common.WearResourceUtil;
import com.android.internal.util.IndentingPrintWriter;
import com.android.wearable.resources.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.LooperMode;
import org.robolectric.shadows.ShadowPackageManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@RunWith(RobolectricTestRunner.class)
@LooperMode(LooperMode.Mode.LEGACY)
public class WearConnectivityPackageManagerTest {
@Mock IndentingPrintWriter mMockIndentingPrintWriter;
private static final int TIMEOUT_MS = 1000;
private static final String[] CELLULAR_PACKAGES = {"com.test.cellular.one",
"com.test.cellular.two", "com.test.cellular.three", "com.test.common.one",
"com.test.common.two"};
private static final String[] WIFI_PACKAGES = {"com.test.wifi.one", "com.test.wifi.two",
"com.test.common.one", "com.test.common.two"};
private static final String[] SUPPRESSED_CELLULAR_PACKAGES = {
"com.test.cellular.suppressed.one", "com.test.cellular.suppressed.two"};
private String[] mCombinedPackages;
private Context mContext;
private WearConnectivityPackageManager mConnectivityPackagemanager;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
Set<String> mCombinedPackagesSet = new HashSet(Arrays.asList(CELLULAR_PACKAGES));
mCombinedPackagesSet.addAll(Arrays.asList(WIFI_PACKAGES));
mCombinedPackages = mCombinedPackagesSet.toArray(new String[0]);
shadowOf(mContext.getPackageManager()).addPackage(WearResourceUtil.WEAR_RESOURCE_PACKAGE);
Resources resources = Resources.create(
mContext, CELLULAR_PACKAGES, WIFI_PACKAGES, SUPPRESSED_CELLULAR_PACKAGES);
ShadowPackageManager.resources.put(WearResourceUtil.WEAR_RESOURCE_PACKAGE, resources);
installPackages(mCombinedPackages);
// sendBroadcastAsUser() is not shadowed and causes the test to hang. Add a wrapper here
// that validates the user and calls sendBroadcast().
Context testContext = new ContextWrapper(mContext) {
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
assertThat(user).isEqualTo(UserHandle.ALL);
getApplicationContext().sendBroadcast(intent);
}
};
mConnectivityPackagemanager = new WearConnectivityPackageManager(testContext);
}
@Test
public void testCellularPackagesEnabled() {
ConditionVariable conditionVariable = getIntentsReceivedCondition(CELLULAR_PACKAGES);
mConnectivityPackagemanager.onCellularRadioState(true);
verifyPackageState(CELLULAR_PACKAGES, PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
assertThat(conditionVariable.block(TIMEOUT_MS)).isTrue();
}
@Test
public void testWifiPackagesEnabled() {
ConditionVariable conditionVariable = getIntentsReceivedCondition(WIFI_PACKAGES);
mConnectivityPackagemanager.onWifiRadioState(true);
verifyPackageState(WIFI_PACKAGES, PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
assertThat(conditionVariable.block(TIMEOUT_MS)).isTrue();
}
@Test
public void testCellularAndWifiPackagesEnabledThenDisabled() {
ArrayList<String> orderedPackages = new ArrayList<String>();
orderedPackages.addAll(Arrays.asList(WIFI_PACKAGES));
for (String app : CELLULAR_PACKAGES) {
if (!orderedPackages.contains(app)) {
orderedPackages.add(app);
}
}
ConditionVariable cv = getIntentsReceivedCondition(orderedPackages.toArray(new String[0]));
mConnectivityPackagemanager.onWifiRadioState(true);
mConnectivityPackagemanager.onCellularRadioState(true);
verifyPackageState(mCombinedPackages, PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
assertThat(cv.block(TIMEOUT_MS)).isTrue();
mConnectivityPackagemanager.onWifiRadioState(false);
mConnectivityPackagemanager.onCellularRadioState(false);
verifyPackageState(mCombinedPackages, PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
}
@Test
public void testDump() {
mConnectivityPackagemanager.dump(mMockIndentingPrintWriter);
verify(mMockIndentingPrintWriter, atLeast(1)).printPair(anyString(), anyInt());
}
private void installPackages(String[] allPackages) {
for (String packageName : allPackages) {
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = packageName;
shadowOf(mContext.getPackageManager()).installPackage(packageInfo);
}
}
private void verifyPackageState(String[] packageNames, int state) {
for (String app : packageNames) {
assertThat(mContext.getPackageManager()
.getApplicationEnabledSetting(app))
.isEqualTo(state);
}
}
private ConditionVariable getIntentsReceivedCondition(String[] apps) {
final ConditionVariable conditionVariable = new ConditionVariable();
mContext.registerReceiver(
new BroadcastReceiver() {
private int mAppIndex = 0;
@Override
public void onReceive(Context context, Intent intent) {
assertThat(intent.getAction())
.isEqualTo(
WearConnectivityPackageManager.ACTION_WEAR_APP_ENABLED);
assertThat(apps[mAppIndex]).isEqualTo(intent.getPackage());
if (++mAppIndex == apps.length) {
conditionVariable.open();
mContext.unregisterReceiver(this);
}
}
},
new IntentFilter(WearConnectivityPackageManager.ACTION_WEAR_APP_ENABLED),
Context.RECEIVER_EXPORTED_UNAUDITED);
return conditionVariable;
}
@Test
public void testSuppressedCellularRequestors() {
for (String name : SUPPRESSED_CELLULAR_PACKAGES) {
assertThat(mConnectivityPackagemanager.isSuppressedCellularRequestor(name)).isTrue();
}
}
/**
* Constructed resources to inject into the ShadowPackageManager.
*/
public static class Resources extends android.content.res.Resources {
private final String[] mCellularPackages;
private final String[] mWifiPackages;
private final String[] mSuppressedCellularRequestors;
private Resources(
String[] cellularPackages,
String[] wifiPackages,
String[] suppressedCellularRequestors,
AssetManager assets,
DisplayMetrics metrics,
Configuration config) {
super(assets, metrics, config);
mCellularPackages = cellularPackages;
mWifiPackages = wifiPackages;
mSuppressedCellularRequestors = suppressedCellularRequestors;
}
public static Resources create(
Context context,
String[] cellularPackages,
String[] wifiPackages,
String[] suppressedCellularRequestors) {
android.content.res.Resources res = context.getResources();
return new Resources(
cellularPackages,
wifiPackages,
suppressedCellularRequestors,
res.getAssets(),
res.getDisplayMetrics(),
res.getConfiguration());
}
@NonNull
@Override
public String[] getStringArray(int id) {
if (id == R.array.config_wearCellularEnabledPackages) {
ArrayList<String> cellularPackagesList = new ArrayList<>();
cellularPackagesList.addAll(Arrays.asList(mCellularPackages));
cellularPackagesList.add("cellular_not_installed");
cellularPackagesList.add("common_not_installed");
return cellularPackagesList.toArray(new String[0]);
}
if (id == R.array.config_wearWifiEnabledPackages) {
ArrayList<String> wifiPackagesList = new ArrayList<>();
wifiPackagesList.addAll(Arrays.asList(mWifiPackages));
wifiPackagesList.add("wifi_not_installed");
wifiPackagesList.add("common_not_installed");
return wifiPackagesList.toArray(new String[0]);
}
if (id == R.array.config_wearSuppressedCellularRequestors) {
return mSuppressedCellularRequestors;
}
throw new NotFoundException();
}
}
}