Slices feature supports device model.
- Migrate DeviceModelPreferenceController to BasePreferenceController - Because Slice feature enables strict mode, we can't do I/O(DeviceInfoUtils.getMsvSuffix) on main thread. Using FutureTask to get around the foreground thread restriction. - Modify test case for new device model controller. Test: slice uri > content://android.settings.slices/intent/my_device_model Test: make RunSettingsRoboTests -j atest UniquePreferenceTest SettingsGatewayTest Change-Id: Idafc132dfa14138ad5a7edd58e63c4b0f644c994
This commit is contained in:
@@ -38,11 +38,12 @@
|
|||||||
|
|
||||||
<!-- Model & hardware -->
|
<!-- Model & hardware -->
|
||||||
<Preference
|
<Preference
|
||||||
android:key="device_model"
|
android:key="device_model_v1"
|
||||||
android:order="21"
|
android:order="21"
|
||||||
android:title="@string/hardware_info"
|
android:title="@string/hardware_info"
|
||||||
settings:keywords="@string/keywords_model_and_hardware"
|
settings:keywords="@string/keywords_model_and_hardware"
|
||||||
android:summary="@string/summary_placeholder" />
|
android:summary="@string/summary_placeholder"
|
||||||
|
settings:controller="com.android.settings.deviceinfo.DeviceModelPreferenceController" />
|
||||||
|
|
||||||
<!-- IMEI -->
|
<!-- IMEI -->
|
||||||
<Preference
|
<Preference
|
||||||
|
@@ -87,7 +87,9 @@
|
|||||||
android:order="21"
|
android:order="21"
|
||||||
android:title="@string/hardware_info"
|
android:title="@string/hardware_info"
|
||||||
settings:keywords="@string/keywords_model_and_hardware"
|
settings:keywords="@string/keywords_model_and_hardware"
|
||||||
android:summary="@string/summary_placeholder"/>
|
android:summary="@string/summary_placeholder"
|
||||||
|
settings:controller=
|
||||||
|
"com.android.settings.deviceinfo.DeviceModelPreferenceController" />
|
||||||
|
|
||||||
<!-- IMEI -->
|
<!-- IMEI -->
|
||||||
<Preference
|
<Preference
|
||||||
|
@@ -21,7 +21,6 @@ import android.app.Fragment;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.provider.SearchIndexableResource;
|
import android.provider.SearchIndexableResource;
|
||||||
import androidx.annotation.VisibleForTesting;
|
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
@@ -41,6 +40,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
@SearchIndexable
|
@SearchIndexable
|
||||||
public class DeviceInfoSettings extends DashboardFragment implements Indexable {
|
public class DeviceInfoSettings extends DashboardFragment implements Indexable {
|
||||||
|
|
||||||
@@ -57,6 +58,7 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable {
|
|||||||
public void onAttach(Context context) {
|
public void onAttach(Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
use(FirmwareVersionPreferenceController.class).setHost(this /*parent*/);
|
use(FirmwareVersionPreferenceController.class).setHost(this /*parent*/);
|
||||||
|
use(DeviceModelPreferenceController.class).setHost(this /* parent */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -134,7 +136,6 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable {
|
|||||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||||
controllers.add(new PhoneNumberPreferenceController(context));
|
controllers.add(new PhoneNumberPreferenceController(context));
|
||||||
controllers.add(new SimStatusPreferenceController(context, fragment));
|
controllers.add(new SimStatusPreferenceController(context, fragment));
|
||||||
controllers.add(new DeviceModelPreferenceController(context, fragment));
|
|
||||||
controllers.add(new ImeiInfoPreferenceController(context, fragment));
|
controllers.add(new ImeiInfoPreferenceController(context, fragment));
|
||||||
controllers.add(new IpAddressPreferenceController(context, lifecycle));
|
controllers.add(new IpAddressPreferenceController(context, lifecycle));
|
||||||
controllers.add(new WifiMacAddressPreferenceController(context, lifecycle));
|
controllers.add(new WifiMacAddressPreferenceController(context, lifecycle));
|
||||||
|
@@ -18,50 +18,54 @@ package com.android.settings.deviceinfo;
|
|||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import androidx.preference.Preference;
|
|
||||||
import androidx.preference.PreferenceScreen;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.PreferenceControllerMixin;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
import com.android.settingslib.DeviceInfoUtils;
|
import com.android.settingslib.DeviceInfoUtils;
|
||||||
import com.android.settingslib.core.AbstractPreferenceController;
|
|
||||||
|
|
||||||
public class DeviceModelPreferenceController extends AbstractPreferenceController implements
|
import java.util.concurrent.Callable;
|
||||||
PreferenceControllerMixin {
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.FutureTask;
|
||||||
|
|
||||||
private static final String KEY_DEVICE_MODEL = "device_model";
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
private final Fragment mHost;
|
|
||||||
|
|
||||||
public DeviceModelPreferenceController(Context context, Fragment host) {
|
public class DeviceModelPreferenceController extends BasePreferenceController {
|
||||||
super(context);
|
|
||||||
mHost = host;
|
private static final String TAG = "DeviceModelPrefCtrl";
|
||||||
|
|
||||||
|
private Fragment mHost;
|
||||||
|
|
||||||
|
public DeviceModelPreferenceController(Context context, String key) {
|
||||||
|
super(context, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setHost(Fragment fragment) {
|
||||||
public boolean isAvailable() {
|
mHost = fragment;
|
||||||
return mContext.getResources().getBoolean(R.bool.config_show_device_model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void displayPreference(PreferenceScreen screen) {
|
public void displayPreference(PreferenceScreen screen) {
|
||||||
super.displayPreference(screen);
|
super.displayPreference(screen);
|
||||||
final Preference pref = screen.findPreference(KEY_DEVICE_MODEL);
|
|
||||||
if (pref != null) {
|
|
||||||
pref.setSummary(mContext.getResources().getString(R.string.model_summary,
|
|
||||||
getDeviceModel()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPreferenceKey() {
|
public int getAvailabilityStatus() {
|
||||||
return KEY_DEVICE_MODEL;
|
return mContext.getResources().getBoolean(R.bool.config_show_device_model)
|
||||||
|
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getSummary() {
|
||||||
|
return mContext.getResources().getString(R.string.model_summary, getDeviceModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||||
if (!TextUtils.equals(preference.getKey(), KEY_DEVICE_MODEL)) {
|
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final HardwareInfoDialogFragment fragment = HardwareInfoDialogFragment.newInstance();
|
final HardwareInfoDialogFragment fragment = HardwareInfoDialogFragment.newInstance();
|
||||||
@@ -70,6 +74,25 @@ public class DeviceModelPreferenceController extends AbstractPreferenceControlle
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getDeviceModel() {
|
public static String getDeviceModel() {
|
||||||
return Build.MODEL + DeviceInfoUtils.getMsvSuffix();
|
FutureTask<String> msvSuffixTask = new FutureTask<String>(new Callable<String>() {
|
||||||
|
@Override
|
||||||
|
public String call() {
|
||||||
|
return DeviceInfoUtils.getMsvSuffix();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
msvSuffixTask.run();
|
||||||
|
try {
|
||||||
|
// Wait for msv suffix value.
|
||||||
|
final String msvSuffix = msvSuffixTask.get();
|
||||||
|
return Build.MODEL + msvSuffix;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
Log.e(TAG, "Execution error, so we only show model name");
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e(TAG, "Interruption error, so we only show model name");
|
||||||
|
}
|
||||||
|
// If we can't get an msv suffix value successfully,
|
||||||
|
// it's better to return model name.
|
||||||
|
return Build.MODEL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -82,6 +82,7 @@ public class MyDeviceInfoFragment extends DashboardFragment
|
|||||||
public void onAttach(Context context) {
|
public void onAttach(Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
use(FirmwareVersionPreferenceController.class).setHost(this /*parent*/);
|
use(FirmwareVersionPreferenceController.class).setHost(this /*parent*/);
|
||||||
|
use(DeviceModelPreferenceController.class).setHost(this /* parent */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -122,7 +123,6 @@ public class MyDeviceInfoFragment extends DashboardFragment
|
|||||||
}
|
}
|
||||||
controllers.add(deviceNamePreferenceController);
|
controllers.add(deviceNamePreferenceController);
|
||||||
controllers.add(new SimStatusPreferenceController(context, fragment));
|
controllers.add(new SimStatusPreferenceController(context, fragment));
|
||||||
controllers.add(new DeviceModelPreferenceController(context, fragment));
|
|
||||||
controllers.add(new ImeiInfoPreferenceController(context, fragment));
|
controllers.add(new ImeiInfoPreferenceController(context, fragment));
|
||||||
controllers.add(new IpAddressPreferenceController(context, lifecycle));
|
controllers.add(new IpAddressPreferenceController(context, lifecycle));
|
||||||
controllers.add(new WifiMacAddressPreferenceController(context, lifecycle));
|
controllers.add(new WifiMacAddressPreferenceController(context, lifecycle));
|
||||||
|
@@ -15,40 +15,44 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.deviceinfo;
|
package com.android.settings.deviceinfo;
|
||||||
|
|
||||||
import static com.android.settings.deviceinfo.DeviceModelPreferenceController.getDeviceModel;
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
|
import android.app.FragmentManager;
|
||||||
|
import android.app.FragmentTransaction;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import androidx.preference.Preference;
|
import android.os.Build;
|
||||||
import androidx.preference.PreferenceScreen;
|
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.core.BasePreferenceController;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Answers;
|
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
public class DeviceModelPreferenceControllerTest {
|
public class DeviceModelPreferenceControllerTest {
|
||||||
|
|
||||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
private final String KEY = "device_model_key";
|
||||||
private Fragment mFragment;
|
|
||||||
@Mock
|
|
||||||
private Preference mPreference;
|
|
||||||
@Mock
|
|
||||||
private PreferenceScreen mPreferenceScreen;
|
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Fragment mFragment;
|
||||||
|
private Preference mPreference;
|
||||||
|
private PreferenceScreen mPreferenceScreen;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private DeviceModelPreferenceController mController;
|
private DeviceModelPreferenceController mController;
|
||||||
|
|
||||||
@@ -56,35 +60,49 @@ public class DeviceModelPreferenceControllerTest {
|
|||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mContext = RuntimeEnvironment.application;
|
mContext = RuntimeEnvironment.application;
|
||||||
mController = new DeviceModelPreferenceController(mContext, mFragment);
|
mController = new DeviceModelPreferenceController(mContext, KEY);
|
||||||
when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
|
mController.setHost(mFragment);
|
||||||
.thenReturn(mPreference);
|
mPreference = new Preference(mContext);
|
||||||
when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
|
mPreference.setKey(KEY);
|
||||||
|
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||||
|
mPreferenceScreen = preferenceManager.createPreferenceScreen(mContext);
|
||||||
|
mPreferenceScreen.addPreference(mPreference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isAvailable_returnTrueIfVisible() {
|
public void isAvailable_returnTrueIfVisible() {
|
||||||
assertThat(mController.isAvailable()).isTrue();
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||||
|
BasePreferenceController.AVAILABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Config(qualifiers = "mcc999")
|
@Config(qualifiers = "mcc999")
|
||||||
public void isAvailable_returnFalseIfNotVisible() {
|
public void isAvailable_returnFalseIfNotVisible() {
|
||||||
assertThat(mController.isAvailable()).isFalse();
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||||
|
BasePreferenceController.UNSUPPORTED_ON_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void displayPref_shouldSetSummary() {
|
public void updatePreference_summaryShouldContainBuildModel() {
|
||||||
mController.displayPreference(mPreferenceScreen);
|
mController.updateState(mPreference);
|
||||||
|
|
||||||
verify(mPreference).setSummary(mContext.getString(R.string.model_summary, getDeviceModel()));
|
assertThat(containBuildModel(mPreference.getSummary())).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void clickPreference_shouldLaunchHardwareInfoDialog() {
|
public void clickPreference_shouldLaunchHardwareInfoDialog() {
|
||||||
|
FragmentManager fragmentManager = mock(FragmentManager.class);
|
||||||
|
when(mFragment.getFragmentManager()).thenReturn(fragmentManager);
|
||||||
|
when(fragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class));
|
||||||
|
|
||||||
assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
|
assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
|
||||||
verify(mFragment).getFragmentManager();
|
verify(fragmentManager.beginTransaction())
|
||||||
verify(mFragment.getFragmentManager().beginTransaction())
|
|
||||||
.add(any(HardwareInfoDialogFragment.class), eq(HardwareInfoDialogFragment.TAG));
|
.add(any(HardwareInfoDialogFragment.class), eq(HardwareInfoDialogFragment.TAG));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean containBuildModel(CharSequence result) {
|
||||||
|
final String oracle = mContext.getResources().getString(R.string.model_summary,
|
||||||
|
Build.MODEL);
|
||||||
|
return result.toString().contains(oracle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user