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:
tmfang
2018-04-25 15:58:54 +08:00
committed by Fan Zhang
parent d43283b53a
commit 5c467566f1
6 changed files with 95 additions and 50 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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));

View File

@@ -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;
} }
} }

View File

@@ -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));

View File

@@ -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);
}
} }