Move SystemUpdateManager.retrieveSystemUpdateInfo

Into Kotlin Coroutine for true async.

Bug: 300851543
Test: manual - on system page
Test: unit test
Change-Id: Ibec5c9d0934d71ed1a5808cadf3b3542eb3d5fa0
This commit is contained in:
Chaohui Wang
2023-09-19 12:28:54 +08:00
parent 47a587ae36
commit cda836fff7
8 changed files with 401 additions and 333 deletions

View File

@@ -16,9 +16,7 @@
package com.android.settings.system;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
@@ -29,9 +27,6 @@ import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
import java.util.Arrays;
import java.util.List;
@SearchIndexable
public class SystemDashboardFragment extends DashboardFragment {
@@ -85,13 +80,5 @@ public class SystemDashboardFragment extends DashboardFragment {
* For Search.
*/
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.system_dashboard_fragment;
return Arrays.asList(sir);
}
};
new BaseSearchIndexProvider(R.xml.system_dashboard_fragment);
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2023 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.system
import android.content.Context
import android.os.Bundle
import android.os.SystemUpdateManager
import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
private const val TAG = "SystemUpdateManagerExt"
/**
* Gets the system update status.
*
* Note: [SystemUpdateManager.retrieveSystemUpdateInfo] must be called on worker thread to avoid
* StrictMode violation.
*/
suspend fun Context.getSystemUpdateInfo(): Bundle? = withContext(Dispatchers.Default) {
val updateManager = getSystemService(SystemUpdateManager::class.java)!!
try {
updateManager.retrieveSystemUpdateInfo()
} catch (e: Exception) {
Log.w(TAG, "Error getting system update info.")
null
}
}

View File

@@ -1,146 +0,0 @@
/*
* Copyright (C) 2016 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.system;
import static android.content.Context.CARRIER_CONFIG_SERVICE;
import static android.content.Context.SYSTEM_UPDATE_SERVICE;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.SystemUpdateManager;
import android.os.UserManager;
import android.telephony.CarrierConfigManager;
import android.text.TextUtils;
import android.util.Log;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class SystemUpdatePreferenceController extends BasePreferenceController {
private static final String TAG = "SysUpdatePrefContr";
private static final String KEY_SYSTEM_UPDATE_SETTINGS = "system_update_settings";
private final UserManager mUm;
private final SystemUpdateManager mUpdateManager;
public SystemUpdatePreferenceController(Context context) {
super(context, KEY_SYSTEM_UPDATE_SETTINGS);
mUm = UserManager.get(context);
mUpdateManager = (SystemUpdateManager) context.getSystemService(SYSTEM_UPDATE_SERVICE);
}
@Override
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(R.bool.config_show_system_update_settings)
&& mUm.isAdminUser()
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
if (isAvailable()) {
Utils.updatePreferenceToSpecificActivityOrRemove(mContext, screen,
getPreferenceKey(),
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
}
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (TextUtils.equals(getPreferenceKey(), preference.getKey())) {
CarrierConfigManager configManager =
(CarrierConfigManager) mContext.getSystemService(CARRIER_CONFIG_SERVICE);
PersistableBundle b = configManager.getConfig();
if (b != null && b.getBoolean(CarrierConfigManager.KEY_CI_ACTION_ON_SYS_UPDATE_BOOL)) {
ciActionOnSysUpdate(b);
}
}
// always return false here because this handler does not want to block other handlers.
return false;
}
@Override
public CharSequence getSummary() {
CharSequence summary = mContext.getString(R.string.android_version_summary,
Build.VERSION.RELEASE_OR_PREVIEW_DISPLAY);
final FutureTask<Bundle> bundleFutureTask = new FutureTask<>(
// Put the API call in a future to avoid StrictMode violation.
() -> mUpdateManager.retrieveSystemUpdateInfo());
final Bundle updateInfo;
try {
bundleFutureTask.run();
updateInfo = bundleFutureTask.get();
} catch (InterruptedException | ExecutionException e) {
Log.w(TAG, "Error getting system update info.");
return summary;
}
switch (updateInfo.getInt(SystemUpdateManager.KEY_STATUS)) {
case SystemUpdateManager.STATUS_WAITING_DOWNLOAD:
case SystemUpdateManager.STATUS_IN_PROGRESS:
case SystemUpdateManager.STATUS_WAITING_INSTALL:
case SystemUpdateManager.STATUS_WAITING_REBOOT:
summary = mContext.getText(R.string.android_version_pending_update_summary);
break;
case SystemUpdateManager.STATUS_UNKNOWN:
Log.d(TAG, "Update statue unknown");
// fall through to next branch
case SystemUpdateManager.STATUS_IDLE:
final String version = updateInfo.getString(SystemUpdateManager.KEY_TITLE);
if (!TextUtils.isEmpty(version)) {
summary = mContext.getString(R.string.android_version_summary, version);
}
break;
}
return summary;
}
/**
* Trigger client initiated action (send intent) on system update
*/
private void ciActionOnSysUpdate(PersistableBundle b) {
String intentStr = b.getString(CarrierConfigManager.
KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING);
if (!TextUtils.isEmpty(intentStr)) {
String extra = b.getString(CarrierConfigManager.
KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING);
String extraVal = b.getString(CarrierConfigManager.
KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING);
Intent intent = new Intent(intentStr);
if (!TextUtils.isEmpty(extra)) {
intent.putExtra(extra, extraVal);
}
Log.d(TAG, "ciActionOnSysUpdate: broadcasting intent " + intentStr +
" with extra " + extra + ", " + extraVal);
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mContext.getApplicationContext().sendBroadcast(intent);
}
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (C) 2023 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.system
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.PersistableBundle
import android.os.SystemUpdateManager
import android.os.UserManager
import android.telephony.CarrierConfigManager
import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.preference.Preference
import androidx.preference.PreferenceScreen
import com.android.settings.R
import com.android.settings.Utils
import com.android.settings.core.BasePreferenceController
import com.android.settingslib.spaprivileged.framework.common.userManager
import kotlinx.coroutines.launch
open class SystemUpdatePreferenceController(context: Context, preferenceKey: String) :
BasePreferenceController(context, preferenceKey) {
private val userManager: UserManager = context.userManager
private lateinit var preference: Preference
override fun getAvailabilityStatus() =
if (mContext.resources.getBoolean(R.bool.config_show_system_update_settings) &&
userManager.isAdminUser
) AVAILABLE else UNSUPPORTED_ON_DEVICE
override fun displayPreference(screen: PreferenceScreen) {
super.displayPreference(screen)
preference = screen.findPreference(preferenceKey)!!
if (isAvailable) {
Utils.updatePreferenceToSpecificActivityOrRemove(
mContext,
screen,
preferenceKey,
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY,
)
}
}
override fun handlePreferenceTreeClick(preference: Preference): Boolean {
if (preferenceKey == preference.key) {
val configManager = mContext.getSystemService(CarrierConfigManager::class.java)!!
configManager.getConfig(CarrierConfigManager.KEY_CI_ACTION_ON_SYS_UPDATE_BOOL)?.let {
if (it.getBoolean(CarrierConfigManager.KEY_CI_ACTION_ON_SYS_UPDATE_BOOL)) {
ciActionOnSysUpdate(it)
}
}
}
// always return false here because this handler does not want to block other handlers.
return false
}
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
preference.summary = calculateSummary()
}
}
}
private suspend fun calculateSummary(): String {
val updateInfo = mContext.getSystemUpdateInfo() ?: return getReleaseVersionSummary()
val status = updateInfo.getInt(SystemUpdateManager.KEY_STATUS)
if (status == SystemUpdateManager.STATUS_UNKNOWN) {
Log.d(TAG, "Update statue unknown")
}
when (status) {
SystemUpdateManager.STATUS_WAITING_DOWNLOAD,
SystemUpdateManager.STATUS_IN_PROGRESS,
SystemUpdateManager.STATUS_WAITING_INSTALL,
SystemUpdateManager.STATUS_WAITING_REBOOT -> {
return mContext.getString(R.string.android_version_pending_update_summary)
}
SystemUpdateManager.STATUS_IDLE,
SystemUpdateManager.STATUS_UNKNOWN -> {
val version = updateInfo.getString(SystemUpdateManager.KEY_TITLE)
if (!version.isNullOrEmpty()) {
return mContext.getString(R.string.android_version_summary, version)
}
}
}
return getReleaseVersionSummary()
}
private fun getReleaseVersionSummary(): String = mContext.getString(
R.string.android_version_summary,
Build.VERSION.RELEASE_OR_PREVIEW_DISPLAY,
)
/**
* Trigger client initiated action (send intent) on system update
*/
private fun ciActionOnSysUpdate(b: PersistableBundle) {
val intentStr = b.getString(CarrierConfigManager.KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING)
if (intentStr.isNullOrEmpty()) return
val extra = b.getString(CarrierConfigManager.KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING)
val extraVal =
b.getString(CarrierConfigManager.KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING)
Log.d(
TAG,
"ciActionOnSysUpdate: broadcasting intent $intentStr with extra $extra, $extraVal"
)
val intent = Intent(intentStr).apply {
if (!extra.isNullOrEmpty()) putExtra(extra, extraVal)
addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND)
}
mContext.applicationContext.sendBroadcast(intent)
}
companion object {
private const val TAG = "SysUpdatePrefContr"
}
}

View File

@@ -53,7 +53,6 @@
<bool name="config_show_pointer_speed">false</bool>
<bool name="config_show_vibrate_input_devices">false</bool>
<bool name="config_show_reset_dashboard">false</bool>
<bool name="config_show_system_update_settings">false</bool>
<bool name="config_show_device_model">false</bool>
<bool name="config_show_top_level_accessibility">false</bool>
<bool name="config_show_top_level_battery">false</bool>

View File

@@ -1,171 +0,0 @@
/*
* Copyright (C) 2016 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.system;
import static android.os.SystemUpdateManager.KEY_STATUS;
import static android.os.SystemUpdateManager.KEY_TITLE;
import static android.os.SystemUpdateManager.STATUS_IDLE;
import static android.os.SystemUpdateManager.STATUS_UNKNOWN;
import static android.os.SystemUpdateManager.STATUS_WAITING_DOWNLOAD;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemUpdateManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowUserManager;
import org.junit.After;
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.Config;
import org.robolectric.shadows.ShadowApplication;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowUserManager.class)
public class SystemUpdatePreferenceControllerTest {
@Mock
private PreferenceScreen mScreen;
@Mock
private SystemUpdateManager mSystemUpdateManager;
private Context mContext;
private ShadowUserManager mShadowUserManager;
private SystemUpdatePreferenceController mController;
private Preference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mShadowUserManager = ShadowUserManager.getShadow();
ShadowApplication.getInstance().setSystemService(Context.SYSTEM_UPDATE_SERVICE,
mSystemUpdateManager);
mController = new SystemUpdatePreferenceController(mContext);
mPreference = new Preference(RuntimeEnvironment.application);
mPreference.setKey(mController.getPreferenceKey());
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
}
@After
public void cleanUp() {
mShadowUserManager.setIsAdminUser(false);
}
@Test
public void updateNonIndexable_ifAvailable_shouldNotUpdate() {
final List<String> keys = new ArrayList<>();
mShadowUserManager.setIsAdminUser(true);
mController.updateNonIndexableKeys(keys);
assertThat(keys).isEmpty();
}
@Test
public void updateNonIndexable_ifNotAvailable_shouldUpdate() {
mShadowUserManager.setIsAdminUser(false);
final List<String> keys = new ArrayList<>();
mController.updateNonIndexableKeys(keys);
assertThat(keys).hasSize(1);
}
@Test
public void displayPrefs_ifVisible_butNotAdminUser_shouldNotDisplay() {
mShadowUserManager.setIsAdminUser(false);
mController.displayPreference(mScreen);
assertThat(mPreference.isVisible()).isFalse();
}
@Test
@Config(qualifiers = "mcc999")
public void displayPrefs_ifAdminUser_butNotVisible_shouldNotDisplay() {
mShadowUserManager.setIsAdminUser(true);
mController.displayPreference(mScreen);
assertThat(mPreference.isVisible()).isFalse();
}
@Test
public void displayPrefs_ifAvailable_shouldDisplay() {
mShadowUserManager.setIsAdminUser(true);
mController.displayPreference(mScreen);
assertThat(mPreference.isVisible()).isTrue();
}
@Test
public void updateState_systemUpdateStatusUnknown_shouldSetToAndroidVersion() {
final Bundle bundle = new Bundle();
bundle.putInt(KEY_STATUS, STATUS_UNKNOWN);
when(mSystemUpdateManager.retrieveSystemUpdateInfo()).thenReturn(bundle);
mController.updateState(mPreference);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.android_version_summary,
Build.VERSION.RELEASE_OR_PREVIEW_DISPLAY));
}
@Test
public void updateState_systemUpdateStatusIdle_shouldSetToAndroidVersion() {
final String testReleaseName = "ANDROID TEST VERSION";
final Bundle bundle = new Bundle();
bundle.putInt(KEY_STATUS, STATUS_IDLE);
bundle.putString(KEY_TITLE, testReleaseName);
when(mSystemUpdateManager.retrieveSystemUpdateInfo()).thenReturn(bundle);
mController.updateState(mPreference);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.android_version_summary, testReleaseName));
}
@Test
public void updateState_systemUpdateInProgress_shouldSetToUpdatePending() {
final Bundle bundle = new Bundle();
bundle.putInt(KEY_STATUS, STATUS_WAITING_DOWNLOAD);
when(mSystemUpdateManager.retrieveSystemUpdateInfo()).thenReturn(bundle);
mController.updateState(mPreference);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.android_version_pending_update_summary));
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2023 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.system
import android.content.Context
import android.os.Bundle
import android.os.SystemUpdateManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class SystemUpdateManagerExtKtTest {
private val mockSystemUpdateManager = mock<SystemUpdateManager>()
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { getSystemService(SystemUpdateManager::class.java) } doReturn mockSystemUpdateManager
}
@Test
fun getSystemUpdateInfo() = runTest {
val bundle = Bundle()
whenever(mockSystemUpdateManager.retrieveSystemUpdateInfo()).thenReturn(bundle)
val info = context.getSystemUpdateInfo()
assertThat(info).isSameInstanceAs(bundle)
}
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright (C) 2023 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.system
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.os.SystemClock
import android.os.SystemUpdateManager
import android.os.UserManager
import androidx.lifecycle.testing.TestLifecycleOwner
import androidx.preference.Preference
import androidx.preference.PreferenceScreen
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
import com.android.settingslib.spaprivileged.framework.common.userManager
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class SystemUpdatePreferenceControllerTest {
private val mockUserManager = mock<UserManager>()
private val mockSystemUpdateManager = mock<SystemUpdateManager>()
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { userManager } doReturn mockUserManager
on { getSystemService(SystemUpdateManager::class.java) } doReturn mockSystemUpdateManager
}
private val resources = spy(context.resources) {
on { getBoolean(R.bool.config_show_system_update_settings) } doReturn true
}
private val preference = Preference(context).apply { key = KEY }
private val preferenceScreen = mock<PreferenceScreen> {
onGeneric { findPreference(KEY) } doReturn preference
}
private val controller = SystemUpdatePreferenceController(context, KEY)
@Before
fun setUp() {
whenever(context.resources).thenReturn(resources)
}
@Test
fun updateNonIndexable_ifAvailable_shouldNotUpdate() {
whenever(mockUserManager.isAdminUser).thenReturn(true)
val keys = mutableListOf<String>()
controller.updateNonIndexableKeys(keys)
assertThat(keys).isEmpty()
}
@Test
fun updateNonIndexable_ifNotAvailable_shouldUpdate() {
whenever(mockUserManager.isAdminUser).thenReturn(false)
val keys = mutableListOf<String>()
controller.updateNonIndexableKeys(keys)
assertThat(keys).containsExactly(KEY)
}
@Test
fun displayPrefs_ifVisible_butNotAdminUser_shouldNotDisplay() {
whenever(mockUserManager.isAdminUser).thenReturn(false)
controller.displayPreference(preferenceScreen)
assertThat(preference.isVisible).isFalse()
}
@Test
fun displayPrefs_ifAdminUser_butNotVisible_shouldNotDisplay() {
whenever(mockUserManager.isAdminUser).thenReturn(true)
whenever(resources.getBoolean(R.bool.config_show_system_update_settings)).thenReturn(false)
controller.displayPreference(preferenceScreen)
assertThat(preference.isVisible).isFalse()
}
@Test
fun displayPrefs_ifAvailable_shouldDisplay() {
whenever(mockUserManager.isAdminUser).thenReturn(true)
controller.displayPreference(preferenceScreen)
assertThat(preference.isVisible).isTrue()
}
@Test
fun updateState_systemUpdateStatusUnknown_shouldSetToAndroidVersion() {
val bundle = Bundle().apply {
putInt(SystemUpdateManager.KEY_STATUS, SystemUpdateManager.STATUS_UNKNOWN)
}
whenever(mockSystemUpdateManager.retrieveSystemUpdateInfo()).thenReturn(bundle)
controller.displayPreference(preferenceScreen)
controller.onViewCreated(TestLifecycleOwner())
SystemClock.sleep(100)
assertThat(preference.summary).isEqualTo(
context.getString(
R.string.android_version_summary,
Build.VERSION.RELEASE_OR_PREVIEW_DISPLAY,
)
)
}
@Test
fun updateState_systemUpdateStatusIdle_shouldSetToAndroidVersion() {
val testReleaseName = "ANDROID TEST VERSION"
val bundle = Bundle().apply {
putInt(SystemUpdateManager.KEY_STATUS, SystemUpdateManager.STATUS_IDLE)
putString(SystemUpdateManager.KEY_TITLE, testReleaseName)
}
whenever(mockSystemUpdateManager.retrieveSystemUpdateInfo()).thenReturn(bundle)
controller.displayPreference(preferenceScreen)
controller.onViewCreated(TestLifecycleOwner())
SystemClock.sleep(100)
assertThat(preference.summary)
.isEqualTo(context.getString(R.string.android_version_summary, testReleaseName))
}
@Test
fun updateState_systemUpdateInProgress_shouldSetToUpdatePending() {
val bundle = Bundle().apply {
putInt(SystemUpdateManager.KEY_STATUS, SystemUpdateManager.STATUS_WAITING_DOWNLOAD)
}
whenever(mockSystemUpdateManager.retrieveSystemUpdateInfo()).thenReturn(bundle)
controller.displayPreference(preferenceScreen)
controller.onViewCreated(TestLifecycleOwner())
SystemClock.sleep(100)
assertThat(preference.summary)
.isEqualTo(context.getString(R.string.android_version_pending_update_summary))
}
private companion object {
const val KEY = "test_key"
}
}