VDM Settings

Demo: go/vdm-settings-demo

Bug: 371713473
Bug: 338974320
Test: atest
Flag: android.companion.virtualdevice.flags.vdm_settings
Change-Id: I4a818b1b31ad59ee3de22105b969aec4c7f4d529
This commit is contained in:
Vladimir Komsiyski
2024-12-19 04:56:35 -08:00
parent 597b3c6480
commit af3e3026ff
22 changed files with 1878 additions and 1 deletions

View File

@@ -0,0 +1,82 @@
/*
* 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.settings.connecteddevice.virtual;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.companion.AssociationInfo;
import android.companion.CompanionDeviceManager;
import android.content.Context;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
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.annotation.Config;
import org.robolectric.shadows.ShadowLooper;
import org.robolectric.shadows.androidx.fragment.FragmentController;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowAlertDialogCompat.class})
public class ForgetDeviceDialogFragmentTest {
private static final int ASSOCIATION_ID = 42;
@Mock
private AssociationInfo mAssociationInfo;
@Mock
private CompanionDeviceManager mCompanionDeviceManager;
private AlertDialog mDialog;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mAssociationInfo.getId()).thenReturn(ASSOCIATION_ID);
VirtualDeviceWrapper device = new VirtualDeviceWrapper(
mAssociationInfo, "PersistentDeviceId", Context.DEVICE_ID_INVALID);
ForgetDeviceDialogFragment fragment = ForgetDeviceDialogFragment.newInstance(device);
FragmentController.setupFragment(fragment, FragmentActivity.class,
0 /* containerViewId */, null /* bundle */);
fragment.mDevice = device;
fragment.mCompanionDeviceManager = mCompanionDeviceManager;
mDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
}
@Test
public void cancelDialog() {
mDialog.getButton(AlertDialog.BUTTON_NEGATIVE).performClick();
ShadowLooper.idleMainLooper();
verify(mCompanionDeviceManager, never()).disassociate(anyInt());
}
@Test
public void confirmDialog() {
mDialog.getButton(AlertDialog.BUTTON_POSITIVE).performClick();
ShadowLooper.idleMainLooper();
verify(mCompanionDeviceManager).disassociate(ASSOCIATION_ID);
}
}

View File

@@ -0,0 +1,166 @@
/*
* 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.settings.connecteddevice.virtual;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.companion.AssociationInfo;
import android.companion.Flags;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settingslib.widget.LayoutPreference;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowLooper;
@RunWith(RobolectricTestRunner.class)
public class VirtualDeviceDetailsHeaderControllerTest {
private static final CharSequence DEVICE_NAME = "Device Name";
private static final int DEVICE_ID = 42;
private static final String PERSISTENT_DEVICE_ID = "PersistentDeviceId";
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock
VirtualDeviceManager mVirtualDeviceManager;
@Mock
AssociationInfo mAssociationInfo;
@Mock
PreferenceScreen mScreen;
private VirtualDeviceWrapper mDevice;
private VirtualDeviceDetailsHeaderController mController;
private TextView mTitle;
private ImageView mIcon;
private TextView mSummary;
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(VirtualDeviceManager.class))
.thenReturn(mVirtualDeviceManager);
mDevice = new VirtualDeviceWrapper(mAssociationInfo, PERSISTENT_DEVICE_ID, DEVICE_ID);
LayoutPreference headerPreference = new LayoutPreference(mContext,
LayoutInflater.from(mContext).inflate(R.layout.settings_entity_header, null));
View view = headerPreference.findViewById(R.id.entity_header);
mTitle = view.findViewById(R.id.entity_header_title);
mIcon = headerPreference.findViewById(R.id.entity_header_icon);
mSummary = view.findViewById(R.id.entity_header_summary);
when(mScreen.findPreference(any())).thenReturn(headerPreference);
mController = new VirtualDeviceDetailsHeaderController(mContext);
mController.init(mDevice);
}
@Test
public void title_matchesDeviceName() {
when(mAssociationInfo.getDisplayName()).thenReturn(DEVICE_NAME);
mController.displayPreference(mScreen);
assertThat(mTitle.getText().toString()).isEqualTo(DEVICE_NAME.toString());
}
@Test
@DisableFlags(Flags.FLAG_ASSOCIATION_DEVICE_ICON)
public void icon_genericIcon() {
mController.displayPreference(mScreen);
assertThat(Shadows.shadowOf(mIcon.getDrawable()).getCreatedFromResId())
.isEqualTo(R.drawable.ic_devices_other);
}
@Test
@EnableFlags(Flags.FLAG_ASSOCIATION_DEVICE_ICON)
public void icon_noAssociationIcon_genericIcon() {
mController.displayPreference(mScreen);
assertThat(Shadows.shadowOf(mIcon.getDrawable()).getCreatedFromResId())
.isEqualTo(R.drawable.ic_devices_other);
}
@Test
@EnableFlags(Flags.FLAG_ASSOCIATION_DEVICE_ICON)
public void icon_fromAssociation() {
Icon icon = Icon.createWithResource(mContext, R.drawable.ic_android);
when(mAssociationInfo.getDeviceIcon()).thenReturn(icon);
mController.displayPreference(mScreen);
assertThat(Shadows.shadowOf(mIcon.getDrawable()).getCreatedFromResId())
.isEqualTo(R.drawable.ic_android);
}
@Test
public void summary_activeDevice_changeToInactive() {
mDevice.setDeviceId(DEVICE_ID);
mController.displayPreference(mScreen);
assertThat(mSummary.getText().toString())
.isEqualTo(mContext.getString(R.string.virtual_device_connected));
mController.onVirtualDeviceClosed(DEVICE_ID);
ShadowLooper.idleMainLooper();
assertThat(mSummary.getText().toString())
.isEqualTo(mContext.getString(R.string.virtual_device_disconnected));
}
@Test
public void summary_inactiveDevice_changeToActive() {
mDevice.setDeviceId(Context.DEVICE_ID_INVALID);
mController.displayPreference(mScreen);
assertThat(mSummary.getText().toString())
.isEqualTo(mContext.getString(R.string.virtual_device_disconnected));
VirtualDevice virtualDevice = mock(VirtualDevice.class);
when(mDevice.getPersistentDeviceId()).thenReturn(PERSISTENT_DEVICE_ID);
when(mVirtualDeviceManager.getVirtualDevice(DEVICE_ID)).thenReturn(virtualDevice);
when(virtualDevice.getPersistentDeviceId()).thenReturn(PERSISTENT_DEVICE_ID);
mController.onVirtualDeviceCreated(DEVICE_ID);
ShadowLooper.idleMainLooper();
assertThat(mSummary.getText().toString())
.isEqualTo(mContext.getString(R.string.virtual_device_connected));
}
}

View File

@@ -0,0 +1,194 @@
/*
* 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.settings.connecteddevice.virtual;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assume.assumeTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.companion.AssociationInfo;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.search.SearchIndexableRaw;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowLooper;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class VirtualDeviceListControllerTest {
private static final String PREFERENCE_KEY = "virtual_device_list";
private static final CharSequence DEVICE_NAME = "Device Name";
private static final int DEVICE_ID = 42;
private static final String PERSISTENT_DEVICE_ID = "PersistentDeviceId";
private static final String DEVICE_PREFERENCE_KEY = PERSISTENT_DEVICE_ID + "_" + DEVICE_NAME;
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock
PreferenceManager mPreferenceManager;
@Mock
AssociationInfo mAssociationInfo;
@Mock
PreferenceScreen mScreen;
private VirtualDeviceWrapper mDevice;
private VirtualDeviceListController mController;
private PreferenceGroup mPreferenceGroup;
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
mPreferenceGroup = spy(new PreferenceScreen(mContext, null));
when(mPreferenceManager.getSharedPreferences()).thenReturn(mock(SharedPreferences.class));
when(mPreferenceGroup.getPreferenceManager()).thenReturn(mPreferenceManager);
when(mScreen.findPreference(PREFERENCE_KEY)).thenReturn(mPreferenceGroup);
when(mScreen.getContext()).thenReturn(mContext);
mController = new VirtualDeviceListController(mContext, PREFERENCE_KEY);
DashboardFragment fragment = mock(DashboardFragment.class);
when(fragment.getContext()).thenReturn(mContext);
mController.setFragment(fragment);
when(mAssociationInfo.getDisplayName()).thenReturn(DEVICE_NAME);
mDevice = new VirtualDeviceWrapper(mAssociationInfo, PERSISTENT_DEVICE_ID, DEVICE_ID);
}
@Test
public void getAvailabilityStatus_vdmDisabled() {
Resources resources = spy(mContext.getResources());
when(mContext.getResources()).thenReturn(resources);
when(resources.getBoolean(com.android.internal.R.bool.config_enableVirtualDeviceManager))
.thenReturn(false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
@DisableFlags(android.companion.virtualdevice.flags.Flags.FLAG_VDM_SETTINGS)
public void getAvailabilityStatus_flagDisabled() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
@EnableFlags(android.companion.virtualdevice.flags.Flags.FLAG_VDM_SETTINGS)
public void getAvailabilityStatus_available() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void onDeviceAdded_createPreference() {
mController.displayPreference(mScreen);
mController.onDeviceAdded(mDevice);
ShadowLooper.idleMainLooper();
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
Preference preference = mPreferenceGroup.findPreference(DEVICE_PREFERENCE_KEY);
assertThat(preference).isNotNull();
assertThat(preference.getTitle().toString()).isEqualTo(DEVICE_NAME.toString());
assertThat(Shadows.shadowOf(preference.getIcon()).getCreatedFromResId())
.isEqualTo(R.drawable.ic_devices_other);
assertThat(preference.getSummary().toString())
.isEqualTo(mContext.getString(R.string.virtual_device_connected));
assertThat(preference).isEqualTo(mController.mPreferences.get(PERSISTENT_DEVICE_ID));
}
@Test
public void onDeviceChanged_updateSummary() {
mController.displayPreference(mScreen);
mController.onDeviceAdded(mDevice);
ShadowLooper.idleMainLooper();
mDevice.setDeviceId(Context.DEVICE_ID_INVALID);
mController.onDeviceChanged(mDevice);
ShadowLooper.idleMainLooper();
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
Preference preference = mPreferenceGroup.findPreference(DEVICE_PREFERENCE_KEY);
assertThat(preference).isNotNull();
assertThat(preference.getSummary().toString())
.isEqualTo(mContext.getString(R.string.virtual_device_disconnected));
assertThat(preference).isEqualTo(mController.mPreferences.get(PERSISTENT_DEVICE_ID));
}
@Test
public void onDeviceRemoved_removePreference() {
mController.displayPreference(mScreen);
mController.onDeviceAdded(mDevice);
ShadowLooper.idleMainLooper();
mDevice.setDeviceId(Context.DEVICE_ID_INVALID);
mController.onDeviceRemoved(mDevice);
ShadowLooper.idleMainLooper();
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
assertThat(mController.mPreferences).isEmpty();
}
@Test
public void updateDynamicRawDataToIndex_available() {
assumeTrue(mController.isAvailable());
mController.mVirtualDeviceUpdater = mock(VirtualDeviceUpdater.class);
when(mController.mVirtualDeviceUpdater.loadDevices()).thenReturn(List.of(mDevice));
ArrayList<SearchIndexableRaw> searchData = new ArrayList<>();
mController.updateDynamicRawDataToIndex(searchData);
assertThat(searchData).hasSize(1);
SearchIndexableRaw data = searchData.getFirst();
assertThat(data.key).isEqualTo(DEVICE_PREFERENCE_KEY);
assertThat(data.title).isEqualTo(DEVICE_NAME.toString());
assertThat(data.summaryOn)
.isEqualTo(mContext.getString(R.string.connected_device_connections_title));
}
}

View File

@@ -0,0 +1,289 @@
/*
* 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.settings.connecteddevice.virtual;
import static com.android.settingslib.drawer.TileUtils.IA_SETTINGS_ACTION;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.companion.AssociationInfo;
import android.companion.CompanionDeviceManager;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
import android.util.ArraySet;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.core.content.pm.ApplicationInfoBuilder;
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.Shadows;
import org.robolectric.shadows.ShadowPackageManager;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class VirtualDeviceUpdaterTest {
private static final String PERSISTENT_DEVICE_ID = "companion:42";
private static final int ASSOCIATION_ID = 42;
private static final int DEVICE_ID = 7;
private static final String PACKAGE_NAME = "test.package.name";
@Mock
private VirtualDeviceManager mVirtualDeviceManager;
@Mock
private CompanionDeviceManager mCompanionDeviceManager;
@Mock
private VirtualDeviceUpdater.DeviceListener mDeviceListener;
@Mock
private AssociationInfo mAssociationInfo;
@Mock
private VirtualDevice mVirtualDevice;
private ShadowPackageManager mPackageManager;
private VirtualDeviceUpdater mVirtualDeviceUpdater;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Context context = spy(ApplicationProvider.getApplicationContext());
when(context.getSystemService(VirtualDeviceManager.class))
.thenReturn(mVirtualDeviceManager);
when(context.getSystemService(CompanionDeviceManager.class))
.thenReturn(mCompanionDeviceManager);
mPackageManager = Shadows.shadowOf(context.getPackageManager());
mVirtualDeviceUpdater = new VirtualDeviceUpdater(context, mDeviceListener);
}
@Test
public void loadDevices_noDevices() {
mVirtualDeviceUpdater.loadDevices();
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).isEmpty();
}
@Test
public void loadDevices_noAssociationInfo() {
when(mVirtualDeviceManager.getAllPersistentDeviceIds())
.thenReturn(new ArraySet<>(new String[]{PERSISTENT_DEVICE_ID}));
mVirtualDeviceUpdater.loadDevices();
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).isEmpty();
}
@Test
public void loadDevices_invalidAssociationId() {
when(mVirtualDeviceManager.getAllPersistentDeviceIds())
.thenReturn(new ArraySet<>(new String[]{"NotACompanionPersistentId"}));
mVirtualDeviceUpdater.loadDevices();
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).isEmpty();
}
@Test
public void loadDevices_noMatchingAssociationId() {
when(mVirtualDeviceManager.getAllPersistentDeviceIds())
.thenReturn(new ArraySet<>(new String[]{PERSISTENT_DEVICE_ID}));
when(mCompanionDeviceManager.getAllAssociations(UserHandle.USER_ALL))
.thenReturn(List.of(mAssociationInfo));
when(mAssociationInfo.getId()).thenReturn(ASSOCIATION_ID + 1);
mVirtualDeviceUpdater.loadDevices();
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).isEmpty();
}
@Test
public void loadDevices_excludePackageFromSettings() {
when(mVirtualDeviceManager.getAllPersistentDeviceIds())
.thenReturn(new ArraySet<>(new String[]{PERSISTENT_DEVICE_ID}));
when(mCompanionDeviceManager.getAllAssociations(UserHandle.USER_ALL))
.thenReturn(List.of(mAssociationInfo));
when(mAssociationInfo.getId()).thenReturn(ASSOCIATION_ID);
when(mAssociationInfo.getPackageName()).thenReturn(PACKAGE_NAME);
final ApplicationInfo appInfo =
ApplicationInfoBuilder.newBuilder().setPackageName(PACKAGE_NAME).build();
final ActivityInfo activityInfo = new ActivityInfo();
activityInfo.packageName = PACKAGE_NAME;
activityInfo.name = PACKAGE_NAME;
activityInfo.applicationInfo = appInfo;
final ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.activityInfo = activityInfo;
final Intent intent = new Intent(IA_SETTINGS_ACTION);
intent.setPackage(PACKAGE_NAME);
mPackageManager.addResolveInfoForIntent(intent, resolveInfo);
mVirtualDeviceUpdater.loadDevices();
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).isEmpty();
}
@Test
public void loadDevices_newDevice_inactive() {
when(mVirtualDeviceManager.getAllPersistentDeviceIds())
.thenReturn(new ArraySet<>(new String[]{PERSISTENT_DEVICE_ID}));
when(mCompanionDeviceManager.getAllAssociations(UserHandle.USER_ALL))
.thenReturn(List.of(mAssociationInfo));
when(mAssociationInfo.getId()).thenReturn(ASSOCIATION_ID);
when(mAssociationInfo.getPackageName()).thenReturn(PACKAGE_NAME);
mVirtualDeviceUpdater.loadDevices();
VirtualDeviceWrapper device = new VirtualDeviceWrapper(
mAssociationInfo, PERSISTENT_DEVICE_ID, Context.DEVICE_ID_INVALID);
verify(mDeviceListener).onDeviceAdded(device);
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).containsExactly(PERSISTENT_DEVICE_ID, device);
}
@Test
public void loadDevices_newDevice_active() {
when(mVirtualDeviceManager.getAllPersistentDeviceIds())
.thenReturn(new ArraySet<>(new String[]{PERSISTENT_DEVICE_ID}));
when(mVirtualDeviceManager.getVirtualDevices())
.thenReturn(List.of(mVirtualDevice));
when(mCompanionDeviceManager.getAllAssociations(UserHandle.USER_ALL))
.thenReturn(List.of(mAssociationInfo));
when(mAssociationInfo.getId()).thenReturn(ASSOCIATION_ID);
when(mAssociationInfo.getPackageName()).thenReturn(PACKAGE_NAME);
when(mVirtualDevice.getDeviceId()).thenReturn(DEVICE_ID);
when(mVirtualDevice.getPersistentDeviceId()).thenReturn(PERSISTENT_DEVICE_ID);
mVirtualDeviceUpdater.loadDevices();
VirtualDeviceWrapper device = new VirtualDeviceWrapper(
mAssociationInfo, PERSISTENT_DEVICE_ID, DEVICE_ID);
verify(mDeviceListener).onDeviceAdded(device);
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).containsExactly(PERSISTENT_DEVICE_ID, device);
}
@Test
public void loadDevices_removeDevice() {
VirtualDeviceWrapper device = new VirtualDeviceWrapper(
mAssociationInfo, PERSISTENT_DEVICE_ID, DEVICE_ID);
mVirtualDeviceUpdater.mDevices.put(PERSISTENT_DEVICE_ID, device);
mVirtualDeviceUpdater.loadDevices();
verify(mDeviceListener).onDeviceRemoved(device);
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).isEmpty();
}
@Test
public void loadDevices_noChanges_activeDevice() {
VirtualDeviceWrapper device = new VirtualDeviceWrapper(
mAssociationInfo, PERSISTENT_DEVICE_ID, DEVICE_ID);
mVirtualDeviceUpdater.mDevices.put(PERSISTENT_DEVICE_ID, device);
when(mVirtualDeviceManager.getAllPersistentDeviceIds())
.thenReturn(new ArraySet<>(new String[]{PERSISTENT_DEVICE_ID}));
when(mVirtualDeviceManager.getVirtualDevices())
.thenReturn(List.of(mVirtualDevice));
when(mCompanionDeviceManager.getAllAssociations(UserHandle.USER_ALL))
.thenReturn(List.of(mAssociationInfo));
when(mAssociationInfo.getId()).thenReturn(ASSOCIATION_ID);
when(mAssociationInfo.getPackageName()).thenReturn(PACKAGE_NAME);
when(mVirtualDevice.getDeviceId()).thenReturn(DEVICE_ID);
when(mVirtualDevice.getPersistentDeviceId()).thenReturn(PERSISTENT_DEVICE_ID);
mVirtualDeviceUpdater.loadDevices();
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).containsExactly(PERSISTENT_DEVICE_ID, device);
}
@Test
public void loadDevices_noChanges_inactiveDevice() {
VirtualDeviceWrapper device = new VirtualDeviceWrapper(
mAssociationInfo, PERSISTENT_DEVICE_ID, Context.DEVICE_ID_INVALID);
mVirtualDeviceUpdater.mDevices.put(PERSISTENT_DEVICE_ID, device);
when(mVirtualDeviceManager.getAllPersistentDeviceIds())
.thenReturn(new ArraySet<>(new String[]{PERSISTENT_DEVICE_ID}));
when(mCompanionDeviceManager.getAllAssociations(UserHandle.USER_ALL))
.thenReturn(List.of(mAssociationInfo));
when(mAssociationInfo.getId()).thenReturn(ASSOCIATION_ID);
when(mAssociationInfo.getPackageName()).thenReturn(PACKAGE_NAME);
mVirtualDeviceUpdater.loadDevices();
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).containsExactly(PERSISTENT_DEVICE_ID, device);
}
@Test
public void loadDevices_deviceChange_activeToInactive() {
VirtualDeviceWrapper device = new VirtualDeviceWrapper(
mAssociationInfo, PERSISTENT_DEVICE_ID, DEVICE_ID);
mVirtualDeviceUpdater.mDevices.put(PERSISTENT_DEVICE_ID, device);
when(mVirtualDeviceManager.getAllPersistentDeviceIds())
.thenReturn(new ArraySet<>(new String[]{PERSISTENT_DEVICE_ID}));
when(mCompanionDeviceManager.getAllAssociations(UserHandle.USER_ALL))
.thenReturn(List.of(mAssociationInfo));
when(mAssociationInfo.getId()).thenReturn(ASSOCIATION_ID);
when(mAssociationInfo.getPackageName()).thenReturn(PACKAGE_NAME);
mVirtualDeviceUpdater.loadDevices();
device.setDeviceId(Context.DEVICE_ID_INVALID);
verify(mDeviceListener).onDeviceChanged(device);
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).containsExactly(PERSISTENT_DEVICE_ID, device);
}
@Test
public void loadDevices_deviceChange_inactiveToActive() {
VirtualDeviceWrapper device = new VirtualDeviceWrapper(
mAssociationInfo, PERSISTENT_DEVICE_ID, Context.DEVICE_ID_INVALID);
mVirtualDeviceUpdater.mDevices.put(PERSISTENT_DEVICE_ID, device);
when(mVirtualDeviceManager.getAllPersistentDeviceIds())
.thenReturn(new ArraySet<>(new String[]{PERSISTENT_DEVICE_ID}));
when(mVirtualDeviceManager.getVirtualDevices())
.thenReturn(List.of(mVirtualDevice));
when(mCompanionDeviceManager.getAllAssociations(UserHandle.USER_ALL))
.thenReturn(List.of(mAssociationInfo));
when(mAssociationInfo.getId()).thenReturn(ASSOCIATION_ID);
when(mAssociationInfo.getPackageName()).thenReturn(PACKAGE_NAME);
when(mVirtualDevice.getDeviceId()).thenReturn(DEVICE_ID);
when(mVirtualDevice.getPersistentDeviceId()).thenReturn(PERSISTENT_DEVICE_ID);
mVirtualDeviceUpdater.loadDevices();
device.setDeviceId(DEVICE_ID);
verify(mDeviceListener).onDeviceChanged(device);
verifyNoMoreInteractions(mDeviceListener);
assertThat(mVirtualDeviceUpdater.mDevices).containsExactly(PERSISTENT_DEVICE_ID, device);
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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.settings.connecteddevice.virtual;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.companion.AssociationInfo;
import android.content.Context;
import com.android.settings.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;
@RunWith(RobolectricTestRunner.class)
public class VirtualDeviceWrapperTest {
private static final String PERSISTENT_DEVICE_ID = "PersistentDeviceIdForTest";
private static final String DEVICE_NAME = "DEVICE NAME";
@Mock
private AssociationInfo mAssociationInfo;
@Mock
private Context mContext;
private VirtualDeviceWrapper mVirtualDeviceWrapper;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mVirtualDeviceWrapper = new VirtualDeviceWrapper(mAssociationInfo, PERSISTENT_DEVICE_ID,
Context.DEVICE_ID_INVALID);
}
@Test
public void setDeviceId() {
assertThat(mVirtualDeviceWrapper.getDeviceId()).isEqualTo(Context.DEVICE_ID_INVALID);
mVirtualDeviceWrapper.setDeviceId(42);
assertThat(mVirtualDeviceWrapper.getDeviceId()).isEqualTo(42);
}
@Test
public void getDisplayName_fromAssociationInfo() {
when(mAssociationInfo.getDisplayName()).thenReturn(DEVICE_NAME);
assertThat(mVirtualDeviceWrapper.getDeviceName(mContext).toString()).isEqualTo(DEVICE_NAME);
}
@Test
public void getDisplayName_fromResources() {
when(mAssociationInfo.getDisplayName()).thenReturn(null);
when(mContext.getString(R.string.virtual_device_unknown)).thenReturn(DEVICE_NAME);
assertThat(mVirtualDeviceWrapper.getDeviceName(mContext).toString()).isEqualTo(DEVICE_NAME);
}
}