diff --git a/res/layout/dialog_hardware_info.xml b/res/layout/dialog_hardware_info.xml new file mode 100644 index 00000000000..f9d52b8ec17 --- /dev/null +++ b/res/layout/dialog_hardware_info.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 4af9cc8d515..0420610f4cb 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2364,6 +2364,10 @@ Android security patch level Model + + Model & hardware + + Hardware version Equipment ID diff --git a/src/com/android/settings/DeviceInfoSettings.java b/src/com/android/settings/DeviceInfoSettings.java index 89ba999585c..e9d3f869ed2 100644 --- a/src/com/android/settings/DeviceInfoSettings.java +++ b/src/com/android/settings/DeviceInfoSettings.java @@ -128,7 +128,7 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable { controllers.add(new BasebandVersionPreferenceController(context)); controllers.add(new FirmwareVersionPreferenceController(context, lifecycle)); controllers.add(new RegulatoryInfoPreferenceController(context)); - controllers.add(new DeviceModelPreferenceController(context)); + controllers.add(new DeviceModelPreferenceController(context, fragment)); controllers.add(new SecurityPatchPreferenceController(context)); controllers.add(new FccEquipmentIdPreferenceController(context)); controllers.add(new SELinuxStatusPreferenceController(context)); diff --git a/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java b/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java index 1b4756172ee..a2c43023610 100644 --- a/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java +++ b/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java @@ -15,10 +15,12 @@ */ package com.android.settings.deviceinfo; +import android.app.Fragment; import android.content.Context; import android.os.Build; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; +import android.text.TextUtils; import com.android.settings.core.PreferenceController; import com.android.settingslib.DeviceInfoUtils; @@ -27,8 +29,11 @@ public class DeviceModelPreferenceController extends PreferenceController { private static final String KEY_DEVICE_MODEL = "device_model"; - public DeviceModelPreferenceController(Context context) { + private final Fragment mHost; + + public DeviceModelPreferenceController(Context context, Fragment host) { super(context); + mHost = host; } @Override @@ -49,4 +54,14 @@ public class DeviceModelPreferenceController extends PreferenceController { public String getPreferenceKey() { return KEY_DEVICE_MODEL; } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (!TextUtils.equals(preference.getKey(), KEY_DEVICE_MODEL)) { + return false; + } + final HardwareInfoDialogFragment fragment = HardwareInfoDialogFragment.newInstance(); + fragment.show(mHost.getFragmentManager(), HardwareInfoDialogFragment.TAG); + return true; + } } diff --git a/src/com/android/settings/deviceinfo/HardwareInfoDialogFragment.java b/src/com/android/settings/deviceinfo/HardwareInfoDialogFragment.java new file mode 100644 index 00000000000..d68b47ac53c --- /dev/null +++ b/src/com/android/settings/deviceinfo/HardwareInfoDialogFragment.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2017 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.deviceinfo; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.os.Build; +import android.os.Bundle; +import android.os.SystemProperties; +import android.support.annotation.VisibleForTesting; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import com.android.internal.logging.nano.MetricsProto; +import com.android.settings.R; +import com.android.settings.core.instrumentation.InstrumentedDialogFragment; +import com.android.settingslib.DeviceInfoUtils; + +public class HardwareInfoDialogFragment extends InstrumentedDialogFragment { + + public static final String TAG = "HardwareInfo"; + + @Override + public int getMetricsCategory() { + return MetricsProto.MetricsEvent.DIALOG_SETTINGS_HARDWARE_INFO; + } + + public static HardwareInfoDialogFragment newInstance() { + final HardwareInfoDialogFragment fragment = new HardwareInfoDialogFragment(); + return fragment; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) + .setTitle(R.string.hardware_info) + .setPositiveButton(android.R.string.ok, null); + final View content = LayoutInflater.from(builder.getContext()) + .inflate(R.layout.dialog_hardware_info, null /* parent */); + // Model + setText(content, R.id.model_label, R.id.model_value, + Build.MODEL + DeviceInfoUtils.getMsvSuffix()); + // Hardware rev + setText(content, R.id.hardware_rev_label, R.id.hardware_rev_value, + SystemProperties.get("ro.boot.hardware.revision")); + + return builder.setView(content).create(); + } + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + void setText(View content, int labelViewId, int valueViewId, String value) { + if (content == null) { + return; + } + final View labelView = content.findViewById(labelViewId); + final TextView valueView = content.findViewById(valueViewId); + if (!TextUtils.isEmpty(value)) { + labelView.setVisibility(View.VISIBLE); + valueView.setVisibility(View.VISIBLE); + valueView.setText(value); + } else { + labelView.setVisibility(View.GONE); + valueView.setVisibility(View.GONE); + } + } +} diff --git a/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java index 06d81decbbb..ea60e4c4469 100644 --- a/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java @@ -16,6 +16,7 @@ package com.android.settings.deviceinfo; +import android.app.Fragment; import android.content.Context; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; @@ -32,15 +33,20 @@ import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class DeviceModelPreferenceControllerTest { + @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Fragment mFragment; @Mock private Preference mPreference; @Mock @@ -50,9 +56,10 @@ public class DeviceModelPreferenceControllerTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - mController = new DeviceModelPreferenceController(mContext); + mController = new DeviceModelPreferenceController(mContext, mFragment); when(mPreferenceScreen.findPreference(mController.getPreferenceKey())) .thenReturn(mPreference); + when(mPreference.getKey()).thenReturn(mController.getPreferenceKey()); } @Test @@ -66,4 +73,13 @@ public class DeviceModelPreferenceControllerTest { verify(mPreference).setSummary(anyString()); } + + @Test + public void clickPreference_shouldLaunchHardwareInfoDialog() { + assertThat(mController.handlePreferenceTreeClick(mPreference)) + .isTrue(); + verify(mFragment).getFragmentManager(); + verify(mFragment.getFragmentManager().beginTransaction()) + .add(any(HardwareInfoDialogFragment.class), eq(HardwareInfoDialogFragment.TAG)); + } } diff --git a/tests/robotests/src/com/android/settings/deviceinfo/HardwareInfoDialogFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/HardwareInfoDialogFragmentTest.java new file mode 100644 index 00000000000..e3dec76eb5d --- /dev/null +++ b/tests/robotests/src/com/android/settings/deviceinfo/HardwareInfoDialogFragmentTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017 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.deviceinfo; + +import android.app.Activity; +import android.os.SystemProperties; +import android.view.View; + +import com.android.settings.R; +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.annotation.Config; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class HardwareInfoDialogFragmentTest { + + private Activity mActivity; + + @Before + public void setUp() { + mActivity = Robolectric.setupActivity(Activity.class); + } + + @Test + public void display_shouldShowHardwareRevision() { + final String TEST_HARDWARE_REV = "123"; + SystemProperties.set("ro.boot.hardware.revision", TEST_HARDWARE_REV); + + final HardwareInfoDialogFragment fragment = spy(HardwareInfoDialogFragment.newInstance()); + fragment.show(mActivity.getFragmentManager(), HardwareInfoDialogFragment.TAG); + + verify(fragment).setText( + any(View.class), eq(R.id.hardware_rev_label), eq(R.id.hardware_rev_value), + eq(TEST_HARDWARE_REV)); + } +}