Snap for 12415101 from d6f73f35b6 to 25Q1-release

Change-Id: I3686d9e294be9b07d62c914ec4ee0a5811d5122a
This commit is contained in:
Android Build Coastguard Worker
2024-09-25 23:23:18 +00:00
61 changed files with 1338 additions and 229 deletions

View File

@@ -571,11 +571,15 @@
<string name="roaming_warning">Roaming charges may apply.</string> <string name="roaming_warning">Roaming charges may apply.</string>
<!-- Date & time setting screen setting switch title: whether the system clock (Unix epoch time) should be determined automatically [CHAR LIMIT=100] --> <!-- Date & time setting screen setting switch title: whether the system clock (Unix epoch time) should be determined automatically [CHAR LIMIT=100] -->
<string name="date_time_auto">Set time automatically</string> <string name="date_time_auto">Automatic date and time</string>
<!-- Date & time setting screen setting switch summary: whether the system clock (Unix epoch time) should be determined automatically [CHAR LIMIT=100] -->
<string name="date_time_auto_summary">Set automatically using your network and wireless signals</string>
<!-- Date & time setting screen setting switch title: whether the time zone should be determined automatically [CHAR LIMIT=100] --> <!-- Date & time setting screen setting switch title: whether the time zone should be determined automatically [CHAR LIMIT=100] -->
<string name="zone_auto_title">Set automatically</string> <string name="zone_auto_title">Automatic time zone</string>
<!-- Date & time setting screen setting switch summary: whether the time zone should be determined automatically [CHAR LIMIT=100] -->
<string name="zone_auto_title_summary">Set automatically based on mobile networks near you</string>
<!-- Date & time setting screen setting switch summary for non-telephony devices [CHAR LIMIT=100] --> <!-- Date & time setting screen setting switch summary for non-telephony devices [CHAR LIMIT=100] -->
<string name="auto_zone_requires_location_summary">Location will be used for setting the time zone when this toggle is on</string> <string name="auto_zone_requires_location_summary">Set automatically using your device location, if available. An active Wifi connection may also be required.</string>
<!-- Date & time setting screen setting option summary text for the automatic 24 hour setting checkbox [CHAR LIMIT=100] --> <!-- Date & time setting screen setting option summary text for the automatic 24 hour setting checkbox [CHAR LIMIT=100] -->
<string name="date_time_24hour_auto">Use locale default</string> <string name="date_time_24hour_auto">Use locale default</string>
<!-- Date & time setting screen setting check box title --> <!-- Date & time setting screen setting check box title -->
@@ -3772,7 +3776,7 @@
<string name="location_services_screen_title">Location services</string> <string name="location_services_screen_title">Location services</string>
<!-- [CHAR LIMIT=60] Date&Time settings screen, toggle button title --> <!-- [CHAR LIMIT=60] Date&Time settings screen, toggle button title -->
<string name="location_time_zone_detection_toggle_title">Use location</string> <string name="location_time_zone_detection_toggle_title">Use location for time zone</string>
<!-- [CHAR LIMIT=50] Date&Time settings screen, title of the dialog when AutoTimeZone is degraded --> <!-- [CHAR LIMIT=50] Date&Time settings screen, title of the dialog when AutoTimeZone is degraded -->
<string name="location_time_zone_detection_status_title">Cannot set the time zone automatically</string> <string name="location_time_zone_detection_status_title">Cannot set the time zone automatically</string>
<!-- Date&Time settings screen, summary of the dialog when AutoTimeZone is degraded by settings--> <!-- Date&Time settings screen, summary of the dialog when AutoTimeZone is degraded by settings-->
@@ -3800,7 +3804,7 @@
<!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is not <!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is not
applicable due to other settings like the "automatic time zone detection enabled" setting applicable due to other settings like the "automatic time zone detection enabled" setting
being set to "off". --> being set to "off". -->
<string name="location_time_zone_detection_auto_is_off">Automatic time zone is off</string> <string name="location_time_zone_detection_auto_is_off">Not available when automatic time zone is off</string>
<!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is not <!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is not
applicable for the user for unspecified reasons. More specific messages are used when there applicable for the user for unspecified reasons. More specific messages are used when there
is a clear reason. --> is a clear reason. -->
@@ -3811,7 +3815,7 @@
allowed for the user, e.g. because of device policy --> allowed for the user, e.g. because of device policy -->
<string name="location_time_zone_detection_not_allowed">Location time zone detection changes are not allowed</string> <string name="location_time_zone_detection_not_allowed">Location time zone detection changes are not allowed</string>
<!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is enabled. --> <!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is enabled. -->
<string name="location_time_zone_detection_auto_is_on">Location may be used to set time zone</string> <string name="location_time_zone_detection_auto_is_on">If your device location is available, it may be used to set your time zone</string>
<!-- Main settings screen, setting summary for the user to go into the About phone screen--> <!-- Main settings screen, setting summary for the user to go into the About phone screen-->
<string name="about_settings_summary">View legal info, status, software version</string> <string name="about_settings_summary">View legal info, status, software version</string>
<!-- About phone settings screen, setting option name to go to dialog that shows legal info --> <!-- About phone settings screen, setting option name to go to dialog that shows legal info -->
@@ -13670,4 +13674,11 @@
<!-- Text for Search bar of Settings home screen [CHAR LIMIT=34] --> <!-- Text for Search bar of Settings home screen [CHAR LIMIT=34] -->
<string name="homepage_search">Search Settings</string> <string name="homepage_search">Search Settings</string>
<!-- Keywords for contacts storage item [CHAR LIMIT=NONE] -->
<string name="keywords_contacts_storage">contacts, storage, account</string>
<!-- Text for Contacts Storage Settings title [CHAR LIMIT=50]-->
<string name="contacts_storage_settings_title">Contacts storage</string>
<!-- Text for displaying when no account is set as default account [CHAR LIMIT=50] -->
<string name="contacts_storage_no_account_set">No default set</string>
</resources> </resources>

View File

@@ -43,7 +43,8 @@
android:title="@string/auto_brightness_title" android:title="@string/auto_brightness_title"
android:fragment="com.android.settings.accessibility.AutoBrightnessPreferenceFragmentForSetupWizard" android:fragment="com.android.settings.accessibility.AutoBrightnessPreferenceFragmentForSetupWizard"
settings:useAdminDisabledSummary="true" settings:useAdminDisabledSummary="true"
settings:userRestriction="no_config_brightness"/> settings:userRestriction="no_config_brightness"
settings:controller="com.android.settings.display.AutoBrightnessPreferenceControllerForSetupWizard"/>
<Preference <Preference
android:fragment="com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragmentForSetupWizard" android:fragment="com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragmentForSetupWizard"

View File

@@ -79,6 +79,15 @@
android:key="dashboard_tile_placeholder" android:key="dashboard_tile_placeholder"
android:order="10"/> android:order="10"/>
<Preference
android:key="contacts_storage"
android:title="@string/contacts_storage_settings_title"
android:summary="@string/summary_placeholder"
android:order="13"
settings:controller="com.android.settings.applications.contacts.ContactsStoragePreferenceController"
settings:keywords="@string/keywords_contacts_storage">
</Preference>
<Preference <Preference
android:key="hibernated_apps" android:key="hibernated_apps"
android:title="@string/unused_apps" android:title="@string/unused_apps"

View File

@@ -23,7 +23,7 @@
<com.android.settingslib.RestrictedSwitchPreference <com.android.settingslib.RestrictedSwitchPreference
android:key="auto_time" android:key="auto_time"
android:title="@string/date_time_auto" android:title="@string/date_time_auto"
settings:useAdditionalSummary="true" android:summary="@string/summary_placeholder"
settings:userRestriction="no_config_date_time" settings:userRestriction="no_config_date_time"
settings:controller="com.android.settings.datetime.AutoTimePreferenceController" /> settings:controller="com.android.settings.datetime.AutoTimePreferenceController" />
@@ -48,6 +48,7 @@
<com.android.settingslib.RestrictedSwitchPreference <com.android.settingslib.RestrictedSwitchPreference
android:key="auto_zone" android:key="auto_zone"
android:title="@string/zone_auto_title" android:title="@string/zone_auto_title"
android:summary="@string/summary_placeholder"
settings:userRestriction="no_config_date_time" settings:userRestriction="no_config_date_time"
settings:controller="com.android.settings.datetime.AutoTimeZonePreferenceController" /> settings:controller="com.android.settings.datetime.AutoTimeZonePreferenceController" />
@@ -60,6 +61,7 @@
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:key="location_time_zone_detection" android:key="location_time_zone_detection"
android:title="@string/location_time_zone_detection_toggle_title" android:title="@string/location_time_zone_detection_toggle_title"
android:summary="@string/summary_placeholder"
settings:controller="com.android.settings.datetime.LocationTimeZoneDetectionPreferenceController"/> settings:controller="com.android.settings.datetime.LocationTimeZoneDetectionPreferenceController"/>
<com.android.settingslib.RestrictedPreference <com.android.settingslib.RestrictedPreference

View File

@@ -17,8 +17,13 @@
package com.android.settings; package com.android.settings;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.deviceinfo.legal.LegalSettingsScreen;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.search.SearchIndexable;
@@ -44,4 +49,10 @@ public class LegalSettings extends DashboardFragment {
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.about_legal); new BaseSearchIndexProvider(R.xml.about_legal);
@Nullable
@Override
public String getPreferenceScreenBindingKey(@NonNull Context context) {
return LegalSettingsScreen.KEY;
}
} }

View File

@@ -41,8 +41,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.display.AutoBrightnessPreferenceController; import com.android.settings.display.BrightnessLevelPreferenceControllerForSetupWizard;
import com.android.settings.display.BrightnessLevelPreferenceController;
import com.android.settingslib.RestrictedPreference; import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
@@ -168,16 +167,10 @@ public class AccessibilitySettingsForSetupWizard extends DashboardFragment
@Override @Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) { protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
// Requires lifecycle, so added programmatically (normally via resId).
final List<AbstractPreferenceController> controllers = new ArrayList<>(); final List<AbstractPreferenceController> controllers = new ArrayList<>();
BrightnessLevelPreferenceController brightnessLevelPreferenceController = controllers.add(new BrightnessLevelPreferenceControllerForSetupWizard(
new BrightnessLevelPreferenceController(context, getSettingsLifecycle()); context, getSettingsLifecycle()));
brightnessLevelPreferenceController.setInSetupWizard(true);
controllers.add(brightnessLevelPreferenceController);
String autoBrightnessKey = context.getString(R.string.preference_key_auto_brightness);
AutoBrightnessPreferenceController autoBrightnessPreferenceController =
new AutoBrightnessPreferenceController(context, autoBrightnessKey);
autoBrightnessPreferenceController.setInSetupWizard(true);
controllers.add(autoBrightnessPreferenceController);
return controllers; return controllers;
} }

View File

@@ -0,0 +1,68 @@
/*
* 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.applications.contacts;
import android.accounts.Account;
import android.content.Context;
import android.os.UserHandle;
import android.provider.ContactsContract;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.flags.Flags;
import com.android.settingslib.accounts.AuthenticatorHelper;
/**
* A preference controller handling the logic for updating summary of contacts default account.
*/
public class ContactsStoragePreferenceController extends BasePreferenceController {
private static final String TAG = "ContactsStorageController";
private final AuthenticatorHelper mAuthenticatorHelper;
public ContactsStoragePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mAuthenticatorHelper = new AuthenticatorHelper(mContext,
new UserHandle(UserHandle.myUserId()), null);
}
@Override
public int getAvailabilityStatus() {
return Flags.enableContactsDefaultAccountInSettings()
? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
public CharSequence getSummary() {
Account currentDefaultAccount =
ContactsContract.Settings.getDefaultAccount(mContext.getContentResolver());
if (currentDefaultAccount == null) {
return mContext.getResources().getString(
R.string.contacts_storage_no_account_set);
}
String accountTypeLabel = (String) mAuthenticatorHelper.getLabelForType(mContext,
currentDefaultAccount.type);
// If there's no account type, or the account type is the same as the
// current default account name, just return the account name.
if (accountTypeLabel == null || accountTypeLabel.equals(currentDefaultAccount.name)) {
return currentDefaultAccount.name;
}
return accountTypeLabel + " | " + currentDefaultAccount.name;
}
}

View File

@@ -359,7 +359,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
String aliasName = device.getAlias(); String aliasName = device.getAlias();
String deviceName = TextUtils.isEmpty(aliasName) ? device.getAddress() String deviceName = TextUtils.isEmpty(aliasName) ? device.getAddress()
: aliasName; : aliasName;
showConnectingDialog("Connecting to " + deviceName + "..."); showConnectingDialog(deviceName);
// Wait for AUTO_DISMISS_TIME_THRESHOLD_MS and check if the paired device supports audio // Wait for AUTO_DISMISS_TIME_THRESHOLD_MS and check if the paired device supports audio
// sharing. // sharing.
if (!mHandler.hasMessages(AUTO_DISMISS_MESSAGE_ID)) { if (!mHandler.hasMessages(AUTO_DISMISS_MESSAGE_ID)) {
@@ -385,14 +385,15 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
} }
// TODO: use DialogFragment // TODO: use DialogFragment
private void showConnectingDialog(@NonNull String message) { private void showConnectingDialog(@NonNull String deviceName) {
postOnMainThread(() -> { postOnMainThread(() -> {
String message = getContext().getString(R.string.progress_dialog_connect_device_content,
deviceName);
if (mProgressDialog != null) { if (mProgressDialog != null) {
Log.d(getLogTag(), "showConnectingDialog, is already showing"); Log.d(getLogTag(), "showConnectingDialog, is already showing");
TextView textView = mProgressDialog.findViewById(R.id.message); TextView textView = mProgressDialog.findViewById(R.id.message);
if (textView != null && !message.equals(textView.getText().toString())) { if (textView != null && !message.equals(textView.getText().toString())) {
Log.d(getLogTag(), "showConnectingDialog, update message"); Log.d(getLogTag(), "showConnectingDialog, update message");
// TODO: use string res once finalized
textView.setText(message); textView.setText(message);
} }
return; return;
@@ -405,7 +406,6 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
null); null);
TextView textView = customView.findViewById(R.id.message); TextView textView = customView.findViewById(R.id.message);
if (textView != null) { if (textView != null) {
// TODO: use string res once finalized
textView.setText(message); textView.setText(message);
} }
AlertDialog dialog = builder.setView(customView).setCancelable(false).create(); AlertDialog dialog = builder.setView(customView).setCancelable(false).create();

View File

@@ -16,6 +16,7 @@
package com.android.settings.bluetooth.ui.model package com.android.settings.bluetooth.ui.model
import android.content.Intent
import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
import com.android.settingslib.bluetooth.devicesettings.shared.model.ToggleModel import com.android.settingslib.bluetooth.devicesettings.shared.model.ToggleModel
@@ -31,7 +32,7 @@ sealed interface DeviceSettingPreferenceModel {
val title: String, val title: String,
val summary: String? = null, val summary: String? = null,
val icon: DeviceSettingIcon? = null, val icon: DeviceSettingIcon? = null,
val onClick: (() -> Unit)? = null, val intent: Intent? = null,
) : DeviceSettingPreferenceModel ) : DeviceSettingPreferenceModel
/** Models a switch preference. */ /** Models a switch preference. */
@@ -42,7 +43,7 @@ sealed interface DeviceSettingPreferenceModel {
val icon: DeviceSettingIcon? = null, val icon: DeviceSettingIcon? = null,
val checked: Boolean, val checked: Boolean,
val onCheckedChange: ((Boolean) -> Unit), val onCheckedChange: ((Boolean) -> Unit),
val onPrimaryClick: (() -> Unit)? = null, val intent: Intent? = null,
) : DeviceSettingPreferenceModel ) : DeviceSettingPreferenceModel
/** Models a multi-toggle preference. */ /** Models a multi-toggle preference. */
@@ -71,6 +72,6 @@ sealed interface DeviceSettingPreferenceModel {
data class HelpPreference( data class HelpPreference(
@DeviceSettingId override val id: Int, @DeviceSettingId override val id: Int,
val icon: DeviceSettingIcon, val icon: DeviceSettingIcon,
val onClick: (() -> Unit), val intent: Intent,
) : DeviceSettingPreferenceModel ) : DeviceSettingPreferenceModel
} }

View File

@@ -18,6 +18,7 @@ package com.android.settings.bluetooth.ui.view
import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothAdapter
import android.content.Context import android.content.Context
import android.content.Intent
import android.media.AudioManager import android.media.AudioManager
import android.os.Bundle import android.os.Bundle
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
@@ -101,13 +102,13 @@ class DeviceDetailsFragmentFormatterImpl(
) : DeviceDetailsFragmentFormatter { ) : DeviceDetailsFragmentFormatter {
private val repository = private val repository =
featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository( featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository(
context, fragment.requireActivity().application,
bluetoothAdapter, bluetoothAdapter,
fragment.lifecycleScope, fragment.lifecycleScope,
) )
private val spatialAudioInteractor = private val spatialAudioInteractor =
featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor( featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor(
context, fragment.requireActivity().application,
context.getSystemService(AudioManager::class.java), context.getSystemService(AudioManager::class.java),
fragment.lifecycleScope, fragment.lifecycleScope,
) )
@@ -312,10 +313,10 @@ class DeviceDetailsFragmentFormatterImpl(
return { deviceSettingIcon(model.icon) } return { deviceSettingIcon(model.icon) }
} }
} }
if (model.onPrimaryClick != null) { if (model.intent != null) {
TwoTargetSwitchPreference( TwoTargetSwitchPreference(
switchPrefModel, switchPrefModel,
primaryOnClick = model.onPrimaryClick::invoke, primaryOnClick = { startActivity(model.intent) },
) )
} else { } else {
SwitchPreference(switchPrefModel) SwitchPreference(switchPrefModel)
@@ -329,7 +330,7 @@ class DeviceDetailsFragmentFormatterImpl(
override val title = model.title override val title = model.title
override val summary = { model.summary ?: "" } override val summary = { model.summary ?: "" }
override val onClick = { override val onClick = {
model.onClick?.invoke() model.intent?.let { startActivity(it) }
Unit Unit
} }
override val icon: (@Composable () -> Unit)? override val icon: (@Composable () -> Unit)?
@@ -361,7 +362,12 @@ class DeviceDetailsFragmentFormatterImpl(
) )
.launch() .launch()
} }
override val icon = @Composable { deviceSettingIcon(null) } override val icon =
@Composable {
deviceSettingIcon(
DeviceSettingIcon.ResourceIcon(R.drawable.ic_chevron_right_24dp)
)
}
} }
) )
} }
@@ -376,6 +382,11 @@ class DeviceDetailsFragmentFormatterImpl(
icon?.let { Icon(it, modifier = Modifier.size(SettingsDimension.itemIconSize)) } icon?.let { Icon(it, modifier = Modifier.size(SettingsDimension.itemIconSize)) }
} }
private fun startActivity(intent: Intent) {
intent.removeFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
}
private fun getPreferenceKey(settingId: Int) = "DEVICE_SETTING_${settingId}" private fun getPreferenceKey(settingId: Int) = "DEVICE_SETTING_${settingId}"
companion object { companion object {

View File

@@ -16,9 +16,11 @@
package com.android.settings.bluetooth.ui.view package com.android.settings.bluetooth.ui.view
import android.app.settings.SettingsEnums
import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothManager
import android.content.Context import android.content.Context
import android.content.Intent
import android.graphics.PorterDuff import android.graphics.PorterDuff
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
@@ -48,8 +50,7 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
private lateinit var cachedDevice: CachedBluetoothDevice private lateinit var cachedDevice: CachedBluetoothDevice
private lateinit var helpItem: StateFlow<DeviceSettingPreferenceModel.HelpPreference?> private lateinit var helpItem: StateFlow<DeviceSettingPreferenceModel.HelpPreference?>
// TODO(b/343317785): add metrics category override fun getMetricsCategory(): Int = SettingsEnums.BLUETOOTH_DEVICE_DETAILS_MORE_SETTINGS
override fun getMetricsCategory(): Int = 0
override fun onPrepareOptionsMenu(menu: Menu) { override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu) super.onPrepareOptionsMenu(menu)
@@ -73,7 +74,10 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
override fun onOptionsItemSelected(menuItem: MenuItem): Boolean { override fun onOptionsItemSelected(menuItem: MenuItem): Boolean {
if (menuItem.itemId == MENU_HELP_ITEM_ID) { if (menuItem.itemId == MENU_HELP_ITEM_ID) {
helpItem.value?.let { it.onClick() } helpItem.value?.intent?.let {
it.removeFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
requireContext().startActivity(it)
}
return true return true
} }
return super.onOptionsItemSelected(menuItem) return super.onOptionsItemSelected(menuItem)

View File

@@ -101,7 +101,7 @@ class BluetoothDeviceDetailsViewModel(
DeviceSettingStateModel.ActionSwitchPreferenceState(newState) DeviceSettingStateModel.ActionSwitchPreferenceState(newState)
) )
}, },
onPrimaryClick = { intent?.let { application.startActivity(it) } }, intent = intent,
) )
} else { } else {
DeviceSettingPreferenceModel.PlainPreference( DeviceSettingPreferenceModel.PlainPreference(
@@ -109,7 +109,7 @@ class BluetoothDeviceDetailsViewModel(
title = title, title = title,
summary = summary, summary = summary,
icon = icon, icon = icon,
onClick = { intent?.let { application.startActivity(it) } }, intent = intent,
) )
} }
} }
@@ -119,7 +119,7 @@ class BluetoothDeviceDetailsViewModel(
DeviceSettingPreferenceModel.HelpPreference( DeviceSettingPreferenceModel.HelpPreference(
id = id, id = id,
icon = DeviceSettingIcon.ResourceIcon(R.drawable.ic_help), icon = DeviceSettingIcon.ResourceIcon(R.drawable.ic_help),
onClick = { application.startActivity(intent) }, intent = intent,
) )
is DeviceSettingModel.MultiTogglePreference -> is DeviceSettingModel.MultiTogglePreference ->
DeviceSettingPreferenceModel.MultiTogglePreference( DeviceSettingPreferenceModel.MultiTogglePreference(

View File

@@ -72,7 +72,7 @@ public class AudioSharingConfirmDialogFragment extends InstrumentedDialogFragmen
.setTitleIcon(com.android.settingslib.R.drawable.ic_bt_le_audio_sharing) .setTitleIcon(com.android.settingslib.R.drawable.ic_bt_le_audio_sharing)
.setIsCustomBodyEnabled(true) .setIsCustomBodyEnabled(true)
.setCustomMessage(R.string.audio_sharing_comfirm_dialog_content) .setCustomMessage(R.string.audio_sharing_comfirm_dialog_content)
.setPositiveButton(com.android.settings.R.string.okay, (d, w) -> {}) .setPositiveButton(R.string.okay, (d, w) -> {})
.build(); .build();
dialog.setCanceledOnTouchOutside(true); dialog.setCanceledOnTouchOutside(true);
return dialog; return dialog;

View File

@@ -26,6 +26,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.BluetoothUtils;
@@ -65,15 +66,13 @@ public class AudioSharingErrorDialogFragment extends InstrumentedDialogFragment
@Override @Override
@NonNull @NonNull
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
// TODO: put strings to res till they are finalized
AlertDialog dialog = AlertDialog dialog =
AudioSharingDialogFactory.newBuilder(getActivity()) AudioSharingDialogFactory.newBuilder(getActivity())
.setTitle("Couldn't share audio") .setTitle(R.string.audio_sharing_retry_dialog_title)
.setTitleIcon(com.android.settings.R.drawable.ic_warning_24dp) .setTitleIcon(R.drawable.ic_warning_24dp)
.setIsCustomBodyEnabled(true) .setIsCustomBodyEnabled(true)
.setCustomMessage("Something went wrong. Please try again.") .setCustomMessage(R.string.audio_sharing_retry_dialog_content)
.setPositiveButton(com.android.settings.R.string.okay, (d, w) -> { .setPositiveButton(R.string.okay, (d, w) -> {})
})
.build(); .build();
dialog.setCanceledOnTouchOutside(true); dialog.setCanceledOnTouchOutside(true);
return dialog; return dialog;

View File

@@ -27,6 +27,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.BluetoothUtils;
@@ -88,15 +89,14 @@ public class AudioSharingIncompatibleDialogFragment extends InstrumentedDialogFr
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Bundle arguments = requireArguments(); Bundle arguments = requireArguments();
String deviceName = arguments.getString(BUNDLE_KEY_DEVICE_NAME); String deviceName = arguments.getString(BUNDLE_KEY_DEVICE_NAME);
// TODO: move strings to res once they are finalized
AlertDialog dialog = AlertDialog dialog =
AudioSharingDialogFactory.newBuilder(getActivity()) AudioSharingDialogFactory.newBuilder(getActivity())
.setTitle("Can't share audio with " + deviceName) .setTitle(getString(R.string.audio_sharing_incompatible_dialog_title,
.setTitleIcon(com.android.settings.R.drawable.ic_warning_24dp) deviceName))
.setTitleIcon(R.drawable.ic_warning_24dp)
.setIsCustomBodyEnabled(true) .setIsCustomBodyEnabled(true)
.setCustomMessage( .setCustomMessage(R.string.audio_sharing_incompatible_dialog_content)
"Audio sharing only works with headphones that support LE Audio.") .setPositiveButton(R.string.okay, (d, w) -> {})
.setPositiveButton(com.android.settings.R.string.okay, (d, w) -> {})
.build(); .build();
dialog.setCanceledOnTouchOutside(true); dialog.setCanceledOnTouchOutside(true);
return dialog; return dialog;

View File

@@ -571,10 +571,10 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
if (mBroadcast != null) { if (mBroadcast != null) {
mBroadcast.startPrivateBroadcast(); mBroadcast.startPrivateBroadcast();
mSinksInAdding.clear(); mSinksInAdding.clear();
// TODO: use string res once finalized.
AudioSharingUtils.postOnMainThread(mContext, AudioSharingUtils.postOnMainThread(mContext,
() -> AudioSharingProgressDialogFragment.show(mFragment, () -> AudioSharingProgressDialogFragment.show(mFragment,
"Starting audio stream...")); mContext.getString(
R.string.audio_sharing_progress_dialog_start_stream_content)));
mMetricsFeatureProvider.action( mMetricsFeatureProvider.action(
mContext, mContext,
SettingsEnums.ACTION_AUDIO_SHARING_MAIN_SWITCH_ON, SettingsEnums.ACTION_AUDIO_SHARING_MAIN_SWITCH_ON,
@@ -830,8 +830,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
private void addSourceToTargetSinks(List<BluetoothDevice> targetActiveSinks, private void addSourceToTargetSinks(List<BluetoothDevice> targetActiveSinks,
@NonNull String sinkName) { @NonNull String sinkName) {
mSinksInAdding.addAll(targetActiveSinks); mSinksInAdding.addAll(targetActiveSinks);
// TODO: move to res once finalized String progressMessage = mContext.getString(
String progressMessage = "Sharing with " + sinkName + "..."; R.string.audio_sharing_progress_dialog_add_source_content, sinkName);
showProgressDialog(progressMessage); showProgressDialog(progressMessage);
AudioSharingUtils.addSourceToTargetSinks(targetActiveSinks, mBtManager); AudioSharingUtils.addSourceToTargetSinks(targetActiveSinks, mBtManager);
} }

View File

@@ -249,6 +249,15 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
@Override @Override
public boolean onPreferenceTreeClick(Preference preference) { public boolean onPreferenceTreeClick(Preference preference) {
if (isCatalystEnabled()) {
Intent intent = preference.getIntent();
if (intent != null && preference.getContext().getPackageManager().queryIntentActivities(
intent, 0).isEmpty()) {
Log.w(TAG, "No activity to start for " + intent);
return true;
}
}
final Collection<List<AbstractPreferenceController>> controllers = final Collection<List<AbstractPreferenceController>> controllers =
mPreferenceControllers.values(); mPreferenceControllers.values();
for (List<AbstractPreferenceController> controllerList : controllers) { for (List<AbstractPreferenceController> controllerList : controllers) {

View File

@@ -27,6 +27,8 @@ import android.app.time.TimeConfiguration;
import android.app.time.TimeManager; import android.app.time.TimeManager;
import android.content.Context; import android.content.Context;
import androidx.preference.Preference;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController; import com.android.settings.core.TogglePreferenceController;
@@ -76,6 +78,17 @@ public class AutoTimePreferenceController extends TogglePreferenceController {
} }
} }
@Override
public void updateState(Preference preference) {
super.updateState(preference);
refreshSummary(preference);
}
@Override
public CharSequence getSummary() {
return mContext.getString(R.string.date_time_auto_summary);
}
@Override @Override
public boolean isChecked() { public boolean isChecked() {
return isEnabled(); return isEnabled();

View File

@@ -129,11 +129,11 @@ public class AutoTimeZonePreferenceController extends TogglePreferenceController
// time zone must use location. // time zone must use location.
if (LocationProviderStatusPreferenceController.hasLocationTimeZoneNoTelephonyFallback( if (LocationProviderStatusPreferenceController.hasLocationTimeZoneNoTelephonyFallback(
mTimeManager.getTimeZoneCapabilitiesAndConfig().getDetectorStatus())) { mTimeManager.getTimeZoneCapabilitiesAndConfig().getDetectorStatus())) {
return mContext.getResources().getString(R.string.auto_zone_requires_location_summary); return mContext.getString(R.string.auto_zone_requires_location_summary);
} }
// If the user has a dedicated toggle to control location use, the summary can
// be empty because the use of location is explicit. // If the user has a dedicated toggle to control location use, explain what it does.
return ""; return mContext.getString(R.string.zone_auto_title_summary);
} }
@VisibleForTesting @VisibleForTesting

View File

@@ -0,0 +1,104 @@
/*
* 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.deviceinfo.firmwareversion
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.SystemClock
import android.os.UserHandle
import android.os.UserManager
import androidx.preference.Preference
import com.android.internal.app.PlatLogoActivity
import com.android.settings.R
import com.android.settings.Utils
import com.android.settingslib.RestrictedLockUtils
import com.android.settingslib.RestrictedLockUtilsInternal
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceSummaryProvider
import com.android.settingslib.preference.PreferenceBinding
// LINT.IfChange
class FirmwareVersionDetailPreference :
PreferenceMetadata,
PreferenceSummaryProvider,
PreferenceBinding,
Preference.OnPreferenceClickListener {
private val hits = LongArray(ACTIVITY_TRIGGER_COUNT)
override val key: String
get() = "os_firmware_version"
override val title: Int
get() = R.string.firmware_version
override fun isIndexable(context: Context) = false
override fun intent(context: Context): Intent? =
Intent(Intent.ACTION_MAIN)
.setClassName("android", PlatLogoActivity::class.java.name)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
override fun getSummary(context: Context): CharSequence? =
Build.VERSION.RELEASE_OR_PREVIEW_DISPLAY
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
super.bind(preference, metadata)
preference.isCopyingEnabled = true
preference.onPreferenceClickListener = this
}
// return true swallows the click event, while return false will start the intent
override fun onPreferenceClick(preference: Preference): Boolean {
if (Utils.isMonkeyRunning()) return true
// remove oldest hit and check whether there are 3 clicks within 500ms
for (index in 1..<ACTIVITY_TRIGGER_COUNT) hits[index - 1] = hits[index]
hits[ACTIVITY_TRIGGER_COUNT - 1] = SystemClock.uptimeMillis()
if (hits[ACTIVITY_TRIGGER_COUNT - 1] - hits[0] > DELAY_TIMER_MILLIS) return true
val context = preference.context
val userManager = context.getSystemService(Context.USER_SERVICE) as? UserManager
if (userManager?.hasUserRestriction(UserManager.DISALLOW_FUN) != true) return false
// Sorry, no fun for you!
val myUserId = UserHandle.myUserId()
val enforcedAdmin =
RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
context,
UserManager.DISALLOW_FUN,
myUserId,
) ?: return true
val disallowedBySystem =
RestrictedLockUtilsInternal.hasBaseUserRestriction(
context,
UserManager.DISALLOW_FUN,
myUserId,
)
if (!disallowedBySystem) {
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(context, enforcedAdmin)
}
return true
}
companion object {
const val DELAY_TIMER_MILLIS = 500L
const val ACTIVITY_TRIGGER_COUNT = 3
}
}
// LINT.ThenChange(FirmwareVersionDetailPreferenceController.java)

View File

@@ -33,6 +33,7 @@ import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedLockUtilsInternal;
// LINT.IfChange
public class FirmwareVersionDetailPreferenceController extends BasePreferenceController { public class FirmwareVersionDetailPreferenceController extends BasePreferenceController {
private static final String TAG = "firmwareDialogCtrl"; private static final String TAG = "firmwareDialogCtrl";
@@ -125,3 +126,4 @@ public class FirmwareVersionDetailPreferenceController extends BasePreferenceCon
mContext, UserManager.DISALLOW_FUN, UserHandle.myUserId()); mContext, UserManager.DISALLOW_FUN, UserHandle.myUserId());
} }
} }
// LINT.ThenChange(FirmwareVersionDetailPreference.kt)

View File

@@ -20,7 +20,6 @@ import android.content.Context
import android.os.Build import android.os.Build
import com.android.settings.R import com.android.settings.R
import com.android.settings.flags.Flags import com.android.settings.flags.Flags
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceSummaryProvider import com.android.settingslib.metadata.PreferenceSummaryProvider
import com.android.settingslib.metadata.ProvidePreferenceScreen import com.android.settingslib.metadata.ProvidePreferenceScreen
import com.android.settingslib.metadata.preferenceHierarchy import com.android.settingslib.metadata.preferenceHierarchy
@@ -47,7 +46,7 @@ class FirmwareVersionScreen : PreferenceScreenCreator, PreferenceSummaryProvider
override fun getPreferenceHierarchy(context: Context) = override fun getPreferenceHierarchy(context: Context) =
preferenceHierarchy(this) { preferenceHierarchy(this) {
+PreferenceWidget("os_firmware_version", R.string.firmware_version) +FirmwareVersionDetailPreference()
+SecurityPatchLevelPreference() +SecurityPatchLevelPreference()
+MainlineModuleVersionPreference() +MainlineModuleVersionPreference()
+BasebandVersionPreference() +BasebandVersionPreference()
@@ -55,9 +54,6 @@ class FirmwareVersionScreen : PreferenceScreenCreator, PreferenceSummaryProvider
+SimpleBuildNumberPreference() +SimpleBuildNumberPreference()
} }
private class PreferenceWidget(override val key: String, override val title: Int) :
PreferenceMetadata
companion object { companion object {
const val KEY = "firmware_version" const val KEY = "firmware_version"
} }

View File

@@ -17,6 +17,7 @@ package com.android.settings.deviceinfo.legal;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
// LINT.IfChange
public class CopyrightPreferenceController extends LegalPreferenceController { public class CopyrightPreferenceController extends LegalPreferenceController {
private static final Intent INTENT = new Intent("android.settings.COPYRIGHT"); private static final Intent INTENT = new Intent("android.settings.COPYRIGHT");
@@ -30,3 +31,4 @@ public class CopyrightPreferenceController extends LegalPreferenceController {
return INTENT; return INTENT;
} }
} }
// LINT.ThenChange(LegalPreference.kt)

View File

@@ -0,0 +1,58 @@
/*
* 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.deviceinfo.legal
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.ResolveInfo
import androidx.annotation.StringRes
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceTitleProvider
// LINT.IfChange
class LegalPreference(
override val key: String,
@StringRes val defaultTitle: Int = 0,
val intentAction: String,
) : PreferenceMetadata, PreferenceTitleProvider, PreferenceAvailabilityProvider {
override fun getTitle(context: Context): CharSequence? {
val resolveInfo =
findMatchingSpecificActivity(context) ?: return context.getText(defaultTitle)
return resolveInfo.loadLabel(context.packageManager)
}
override fun isAvailable(context: Context) = (findMatchingSpecificActivity(context) != null)
override fun intent(context: Context) =
findMatchingSpecificActivity(context)?.let {
Intent()
.setClassName(it.activityInfo.packageName, it.activityInfo.name)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
private fun findMatchingSpecificActivity(context: Context): ResolveInfo? {
val intent = Intent(intentAction)
// Find the activity that is in the system image
val list: List<ResolveInfo> = context.packageManager.queryIntentActivities(intent, 0)
return list.firstOrNull {
(it.activityInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM) != 0
}
}
}
// LINT.ThenChange(LegalPreferenceController.java)

View File

@@ -27,6 +27,7 @@ import com.android.settings.core.BasePreferenceController;
import java.util.List; import java.util.List;
// LINT.IfChange
public abstract class LegalPreferenceController extends BasePreferenceController { public abstract class LegalPreferenceController extends BasePreferenceController {
private final PackageManager mPackageManager; private final PackageManager mPackageManager;
private Preference mPreference; private Preference mPreference;
@@ -94,3 +95,4 @@ public abstract class LegalPreferenceController extends BasePreferenceController
mPreference.setTitle(resolveInfo.loadLabel(mPackageManager)); mPreference.setTitle(resolveInfo.loadLabel(mPackageManager));
} }
} }
// LINT.ThenChange(LegalPreference.kt)

View File

@@ -0,0 +1,55 @@
/*
* 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.deviceinfo.legal
import android.content.Context
import com.android.settings.LegalSettings
import com.android.settings.R
import com.android.settings.flags.Flags
import com.android.settingslib.metadata.ProvidePreferenceScreen
import com.android.settingslib.metadata.preferenceHierarchy
import com.android.settingslib.preference.PreferenceScreenCreator
@ProvidePreferenceScreen
open class LegalSettingsScreen : PreferenceScreenCreator {
override val key: String
get() = KEY
override val title: Int
get() = R.string.legal_information
override fun isFlagEnabled(context: Context) = Flags.catalystLegalInformation()
override fun fragmentClass() = LegalSettings::class.java
override fun getPreferenceHierarchy(context: Context) =
preferenceHierarchy(this) {
+LegalPreference("copyright", R.string.copyright_title, "android.settings.COPYRIGHT")
+LegalPreference("license", R.string.license_title, "android.settings.LICENSE")
+LegalPreference("terms", R.string.terms_title, "android.settings.TERMS")
+ModuleLicensesScreen.KEY // Use screen key in case it is overlaid.
+LegalPreference(
"webview_license",
R.string.webview_license_title,
"android.settings.WEBVIEW_LICENSE",
)
+WallpaperAttributionsPreference()
}
companion object {
const val KEY = "legal_information"
}
}

View File

@@ -17,6 +17,7 @@ package com.android.settings.deviceinfo.legal;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
// LINT.IfChange
public class LicensePreferenceController extends LegalPreferenceController { public class LicensePreferenceController extends LegalPreferenceController {
private static final Intent INTENT = new Intent("android.settings.LICENSE"); private static final Intent INTENT = new Intent("android.settings.LICENSE");
@@ -30,3 +31,4 @@ public class LicensePreferenceController extends LegalPreferenceController {
return INTENT; return INTENT;
} }
} }
// LINT.ThenChange(LegalPreference.kt)

View File

@@ -24,6 +24,7 @@ import com.android.settings.core.BasePreferenceController;
import java.util.List; import java.util.List;
// LINT.IfChange
public class ModuleLicensesListPreferenceController extends BasePreferenceController { public class ModuleLicensesListPreferenceController extends BasePreferenceController {
public ModuleLicensesListPreferenceController(Context context, public ModuleLicensesListPreferenceController(Context context,
String preferenceKey) { String preferenceKey) {
@@ -39,3 +40,4 @@ public class ModuleLicensesListPreferenceController extends BasePreferenceContro
: CONDITIONALLY_UNAVAILABLE; : CONDITIONALLY_UNAVAILABLE;
} }
} }
// LINT.ThenChange(ModuleLicensesScreen.kt)

View File

@@ -0,0 +1,61 @@
/*
* 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.deviceinfo.legal
import android.content.Context
import com.android.settings.R
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.ProvidePreferenceScreen
import com.android.settingslib.metadata.preferenceHierarchy
import com.android.settingslib.preference.PreferenceScreenCreator
// LINT.IfChange
@ProvidePreferenceScreen
class ModuleLicensesScreen : PreferenceScreenCreator, PreferenceAvailabilityProvider {
override val key: String
get() = KEY
override val title: Int
get() = R.string.module_license_title
// We need to avoid directly assign fragment attribute in the bind() API. So we need to create
// a screen and provide it to its parent screen LegalSettingsScreen.
// By the way, we also need to set the isFlagEnabled() as false. Let system render the legacy
// UI. The hierarchy will be added while migrating this page.
override fun isFlagEnabled(context: Context) = false
override fun fragmentClass() = ModuleLicensesDashboard::class.java
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
override fun isAvailable(context: Context): Boolean {
val modules = context.packageManager.getInstalledModules(/* flags= */ 0)
return modules.any {
try {
ModuleLicenseProvider.getPackageAssetManager(context.packageManager, it.packageName)
.list("")
?.contains(ModuleLicenseProvider.GZIPPED_LICENSE_FILE_NAME) == true
} catch (e: Exception) {
false
}
}
}
companion object {
const val KEY = "module_license"
}
}
// LINT.ThenChange(ModuleLicensesListPreferenceController.java)

View File

@@ -17,6 +17,7 @@ package com.android.settings.deviceinfo.legal;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
// LINT.IfChange
public class TermsPreferenceController extends LegalPreferenceController { public class TermsPreferenceController extends LegalPreferenceController {
private static final Intent INTENT = new Intent("android.settings.TERMS"); private static final Intent INTENT = new Intent("android.settings.TERMS");
@@ -30,3 +31,4 @@ public class TermsPreferenceController extends LegalPreferenceController {
return INTENT; return INTENT;
} }
} }
// LINT.ThenChange(LegalPreference.kt)

View File

@@ -0,0 +1,49 @@
/*
* 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.deviceinfo.legal
import android.content.Context
import androidx.preference.Preference
import com.android.settings.R
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.preference.PreferenceBinding
// LINT.IfChange
class WallpaperAttributionsPreference :
PreferenceMetadata, PreferenceBinding, PreferenceAvailabilityProvider {
override val key: String
get() = KEY
override val title: Int
get() = R.string.wallpaper_attributions
override val summary: Int
get() = R.string.wallpaper_attributions_values
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
super.bind(preference, metadata)
preference.isSelectable = false
}
override fun isAvailable(context: Context) =
context.resources.getBoolean(R.bool.config_show_wallpaper_attribution)
companion object {
const val KEY = "wallpaper_attributions"
}
}
// LINT.ThenChange(WallpaperAttributionsPreferenceController.java)

View File

@@ -20,6 +20,7 @@ import android.content.Context;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
// LINT.IfChange
public class WallpaperAttributionsPreferenceController extends BasePreferenceController { public class WallpaperAttributionsPreferenceController extends BasePreferenceController {
public WallpaperAttributionsPreferenceController(Context context, String key) { public WallpaperAttributionsPreferenceController(Context context, String key) {
@@ -33,3 +34,4 @@ public class WallpaperAttributionsPreferenceController extends BasePreferenceCon
: UNSUPPORTED_ON_DEVICE; : UNSUPPORTED_ON_DEVICE;
} }
} }
// LINT.ThenChange(WallpaperAttributionsPreference.kt)

View File

@@ -17,6 +17,7 @@ package com.android.settings.deviceinfo.legal;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
// LINT.IfChange
public class WebViewLicensePreferenceController extends LegalPreferenceController { public class WebViewLicensePreferenceController extends LegalPreferenceController {
private static final Intent INTENT = new Intent("android.settings.WEBVIEW_LICENSE"); private static final Intent INTENT = new Intent("android.settings.WEBVIEW_LICENSE");
@@ -30,3 +31,4 @@ public class WebViewLicensePreferenceController extends LegalPreferenceControlle
return INTENT; return INTENT;
} }
} }
// LINT.ThenChange(LegalPreference.kt)

View File

@@ -22,28 +22,25 @@ import android.os.Process;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings; import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.accessibility.Flags;
import com.android.settings.core.TogglePreferenceController; import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.PrimarySwitchPreference; import com.android.settingslib.PrimarySwitchPreference;
/**
* The top-level preference controller that updates the adaptive brightness.
*/
public class AutoBrightnessPreferenceController extends TogglePreferenceController { public class AutoBrightnessPreferenceController extends TogglePreferenceController {
private final String SYSTEM_KEY = SCREEN_BRIGHTNESS_MODE; private final String SYSTEM_KEY = SCREEN_BRIGHTNESS_MODE;
private final int DEFAULT_VALUE = SCREEN_BRIGHTNESS_MODE_MANUAL; private final int DEFAULT_VALUE = SCREEN_BRIGHTNESS_MODE_MANUAL;
private boolean mInSetupWizard; public AutoBrightnessPreferenceController(@NonNull Context context, @NonNull String key) {
public AutoBrightnessPreferenceController(Context context, String key) {
super(context, key); super(context, key);
} }
public void setInSetupWizard(boolean inSetupWizard) {
mInSetupWizard = inSetupWizard;
}
@Override @Override
public boolean isChecked() { public boolean isChecked() {
return Settings.System.getInt(mContext.getContentResolver(), return Settings.System.getInt(mContext.getContentResolver(),
@@ -60,14 +57,10 @@ public class AutoBrightnessPreferenceController extends TogglePreferenceControll
@Override @Override
@AvailabilityStatus @AvailabilityStatus
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
if (!mContext.getResources().getBoolean( return mContext.getResources().getBoolean(
com.android.internal.R.bool.config_automatic_brightness_available)) { com.android.internal.R.bool.config_automatic_brightness_available)
return UNSUPPORTED_ON_DEVICE; ? AVAILABLE_UNSEARCHABLE
} : UNSUPPORTED_ON_DEVICE;
if (mInSetupWizard && !Flags.addBrightnessSettingsInSuw()) {
return CONDITIONALLY_UNAVAILABLE;
}
return AVAILABLE_UNSEARCHABLE;
} }
@Override @Override

View File

@@ -0,0 +1,44 @@
/*
* 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.display;
import android.content.Context;
import androidx.annotation.NonNull;
import com.android.settings.accessibility.Flags;
/**
* The top-level preference controller that updates the adaptive brightness in the SetupWizard.
*/
public class AutoBrightnessPreferenceControllerForSetupWizard
extends AutoBrightnessPreferenceController {
public AutoBrightnessPreferenceControllerForSetupWizard(@NonNull Context context,
@NonNull String key) {
super(context, key);
}
@Override
@AvailabilityStatus
public int getAvailabilityStatus() {
if (!Flags.addBrightnessSettingsInSuw()) {
return CONDITIONALLY_UNAVAILABLE;
}
return super.getAvailabilityStatus();
}
}

View File

@@ -20,7 +20,6 @@ import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX;
import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MIN; import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MIN;
import static com.android.settingslib.display.BrightnessUtils.convertLinearToGammaFloat; import static com.android.settingslib.display.BrightnessUtils.convertLinearToGammaFloat;
import android.annotation.Nullable;
import android.app.ActivityOptions; import android.app.ActivityOptions;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
@@ -37,12 +36,13 @@ import android.os.UserManager;
import android.provider.Settings.System; import android.provider.Settings.System;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.accessibility.Flags;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SettingsBaseActivity; import com.android.settings.core.SettingsBaseActivity;
@@ -54,18 +54,17 @@ import com.android.settingslib.transition.SettingsTransitionHelper;
import java.text.NumberFormat; import java.text.NumberFormat;
/**
* The top-level preference controller that updates the adaptive brightness level.
*/
public class BrightnessLevelPreferenceController extends BasePreferenceController implements public class BrightnessLevelPreferenceController extends BasePreferenceController implements
PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop { PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop {
private static final String TAG = "BrightnessPrefCtrl";
private static final Uri BRIGHTNESS_ADJ_URI; private static final Uri BRIGHTNESS_ADJ_URI;
private final ContentResolver mContentResolver; private final ContentResolver mContentResolver;
private final Handler mHandler = new Handler(Looper.getMainLooper()); private final Handler mHandler = new Handler(Looper.getMainLooper());
private final DisplayManager mDisplayManager; private final DisplayManager mDisplayManager;
@Nullable @Nullable
private Preference mPreference; private Preference mPreference;
private boolean mInSetupWizard;
static { static {
BRIGHTNESS_ADJ_URI = System.getUriFor(System.SCREEN_AUTO_BRIGHTNESS_ADJ); BRIGHTNESS_ADJ_URI = System.getUriFor(System.SCREEN_AUTO_BRIGHTNESS_ADJ);
@@ -94,11 +93,13 @@ public class BrightnessLevelPreferenceController extends BasePreferenceControlle
} }
}; };
public BrightnessLevelPreferenceController(Context context, Lifecycle lifecycle) { public BrightnessLevelPreferenceController(@NonNull Context context,
@Nullable Lifecycle lifecycle) {
this(context, context.getString(R.string.preference_key_brightness_level), lifecycle); this(context, context.getString(R.string.preference_key_brightness_level), lifecycle);
} }
private BrightnessLevelPreferenceController(Context context, String key, Lifecycle lifecycle) { private BrightnessLevelPreferenceController(@NonNull Context context, @NonNull String key,
@Nullable Lifecycle lifecycle) {
super(context, key); super(context, key);
mDisplayManager = context.getSystemService(DisplayManager.class); mDisplayManager = context.getSystemService(DisplayManager.class);
@@ -108,15 +109,8 @@ public class BrightnessLevelPreferenceController extends BasePreferenceControlle
mContentResolver = mContext.getContentResolver(); mContentResolver = mContext.getContentResolver();
} }
public void setInSetupWizard(boolean inSetupWizard) {
mInSetupWizard = inSetupWizard;
}
@Override @Override
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
if (mInSetupWizard && !Flags.addBrightnessSettingsInSuw()) {
return CONDITIONALLY_UNAVAILABLE;
}
return AVAILABLE; return AVAILABLE;
} }

View File

@@ -0,0 +1,47 @@
/*
* 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.display;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settings.accessibility.Flags;
import com.android.settingslib.core.lifecycle.Lifecycle;
/**
* The top-level preference controller that updates the adaptive brightness level in the
* SetupWizard.
*/
public class BrightnessLevelPreferenceControllerForSetupWizard extends
BrightnessLevelPreferenceController {
public BrightnessLevelPreferenceControllerForSetupWizard(@NonNull Context context,
@Nullable Lifecycle lifecycle) {
super(context, lifecycle);
}
@Override
@AvailabilityStatus
public int getAvailabilityStatus() {
if (!Flags.addBrightnessSettingsInSuw()) {
return CONDITIONALLY_UNAVAILABLE;
}
return super.getAvailabilityStatus();
}
}

View File

@@ -46,8 +46,7 @@ import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.display.AutoBrightnessPreferenceController; import com.android.settings.display.BrightnessLevelPreferenceControllerForSetupWizard;
import com.android.settings.display.BrightnessLevelPreferenceController;
import com.android.settingslib.RestrictedPreference; import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
@@ -146,16 +145,15 @@ public class AccessibilitySettingsForSetupWizardTest {
} }
@Test @Test
public void createPreferenceControllers_brightnessPreferencesControllersAreCreated() { public void createPreferenceControllers_lifeCycleDependencyControllerIsCreated() {
mFragment.onAttach(mContext); mFragment.onAttach(mContext);
List<AbstractPreferenceController> controllers = List<AbstractPreferenceController> controllers =
mFragment.createPreferenceControllers(mContext); mFragment.createPreferenceControllers(mContext);
assertTrue(controllers.stream().anyMatch( assertTrue(controllers.stream().anyMatch(
controller -> controller instanceof BrightnessLevelPreferenceController)); controller ->
assertTrue(controllers.stream().anyMatch( controller instanceof BrightnessLevelPreferenceControllerForSetupWizard));
controller -> controller instanceof AutoBrightnessPreferenceController));
} }
private void addEnabledServiceInfo(ComponentName componentName, boolean isAccessibilityTool) { private void addEnabledServiceInfo(ComponentName componentName, boolean isAccessibilityTool) {

View File

@@ -0,0 +1,162 @@
/*
* 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.applications.contacts;
import static android.provider.ContactsContract.Settings.KEY_DEFAULT_ACCOUNT;
import static android.provider.ContactsContract.Settings.QUERY_DEFAULT_ACCOUNT_METHOD;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.ContactsContract;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import com.android.settings.testutils.shadow.ShadowAuthenticationHelper;
import org.junit.Before;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowAuthenticationHelper.class)
public class ContactsStoragePreferenceControllerTest {
private static final String CONTACTS_DEFAULT_ACCOUNT_PREFERENCE_KEY =
"contacts_default_account";
private static final Account TEST_ACCOUNT1 = new Account("test@gmail.com", "type1");
private static final Account TEST_ACCOUNT2 = new Account("test@samsung.com", "type2");
private static final Account TEST_ACCOUNT3 = new Account("LABEL3", "type3");
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock
private Context mContext;
@Mock
private ContentResolver mContentResolver;
@Mock
private Resources mResources;
@Mock
private AccountManager mAccountManager;
private ContactsStoragePreferenceController mPreferenceController;
@Before
public void setUp() throws Exception {
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getSystemService(eq(Context.ACCOUNT_SERVICE))).thenReturn(mAccountManager);
when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[]{});
mPreferenceController = new ContactsStoragePreferenceController(mContext,
CONTACTS_DEFAULT_ACCOUNT_PREFERENCE_KEY);
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_CONTACTS_DEFAULT_ACCOUNT_IN_SETTINGS)
public void getAvailabilityStatus_flagIsOn_shouldReturnAvailable() {
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_CONTACTS_DEFAULT_ACCOUNT_IN_SETTINGS)
public void getAvailabilityStatus_flagIsOff_shouldReturnConditionallyUnavailable() {
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getSummary_noAccountIsSetAsDefault_shouldReturnNoAccountSetSummary() {
Bundle bundle = new Bundle();
bundle.putParcelable(KEY_DEFAULT_ACCOUNT, null);
when(mContentResolver.call(eq(ContactsContract.AUTHORITY_URI),
eq(QUERY_DEFAULT_ACCOUNT_METHOD), any(), any())).thenReturn(bundle);
when(mContext.getResources()).thenReturn(mResources);
when(mResources.getString(eq(R.string.contacts_storage_no_account_set))).thenReturn(
"No default set");
assertThat(mPreferenceController.getSummary()).isEqualTo("No default set");
}
@Test
public void getSummary_googleAccountIsSetAsDefault_shouldReturnGoogleAccountTypeAndAccountName() {
Bundle bundle = new Bundle();
bundle.putParcelable(KEY_DEFAULT_ACCOUNT, TEST_ACCOUNT1);
when(mContentResolver.call(eq(ContactsContract.AUTHORITY_URI),
eq(QUERY_DEFAULT_ACCOUNT_METHOD), any(), any())).thenReturn(bundle);
assertThat(mPreferenceController.getSummary()).isEqualTo("LABEL1 | test@gmail.com");
}
@Test
public void getSummary_samsungAccountIsSetAsDefault_shouldReturnSamsungAccountTypeAndAccountName() {
Bundle bundle = new Bundle();
bundle.putParcelable(KEY_DEFAULT_ACCOUNT, TEST_ACCOUNT2);
when(mContentResolver.call(eq(ContactsContract.AUTHORITY_URI),
eq(QUERY_DEFAULT_ACCOUNT_METHOD), any(), any())).thenReturn(bundle);
assertThat(mPreferenceController.getSummary()).isEqualTo("LABEL2 | test@samsung.com");
}
@Test
public void getSummary_accountLabelSameAsAccountName_onlyReturnAccountName() {
Bundle bundle = new Bundle();
bundle.putParcelable(KEY_DEFAULT_ACCOUNT, TEST_ACCOUNT3);
when(mContentResolver.call(eq(ContactsContract.AUTHORITY_URI),
eq(QUERY_DEFAULT_ACCOUNT_METHOD), any(), any())).thenReturn(bundle);
// Since package name and account name is the same, we only return account name.
assertThat(mPreferenceController.getSummary()).isEqualTo("LABEL3");
}
}

View File

@@ -211,9 +211,9 @@ public class BluetoothDevicePairingDetailBaseTest {
assertThat(dialog).isNotNull(); assertThat(dialog).isNotNull();
TextView message = dialog.findViewById(R.id.message); TextView message = dialog.findViewById(R.id.message);
assertThat(message).isNotNull(); assertThat(message).isNotNull();
// TODO: use stringr res once finalized
assertThat(message.getText().toString()).isEqualTo( assertThat(message.getText().toString()).isEqualTo(
"Connecting to " + TEST_DEVICE_ADDRESS + "..."); mContext.getString(R.string.progress_dialog_connect_device_content,
TEST_DEVICE_ADDRESS));
verify(mFragment, never()).finish(); verify(mFragment, never()).finish();
} }

View File

@@ -178,11 +178,9 @@ class DeviceDetailsFragmentFormatterTest {
}.launchIn(testScope.backgroundScope) }.launchIn(testScope.backgroundScope)
delay(100) delay(100)
runCurrent() runCurrent()
helpPreference!!.onClick()
ShadowLooper.idleMainLooper() ShadowLooper.idleMainLooper()
val shadowActivity = Shadows.shadowOf(fragmentActivity) assertThat(helpPreference?.intent).isSameInstanceAs(intent)
assertThat(shadowActivity.nextStartedActivity).isSameInstanceAs(intent)
} }
} }

View File

@@ -24,11 +24,13 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes;
import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.flag.junit.SetFlagsRule;
import android.view.View; import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settingslib.flags.Flags; import com.android.settingslib.flags.Flags;
@@ -114,6 +116,10 @@ public class AudioSharingErrorDialogFragmentTest {
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull(); assertThat(dialog).isNotNull();
assertThat(dialog.isShowing()).isTrue(); assertThat(dialog.isShowing()).isTrue();
TextView title = dialog.findViewById(R.id.title_text);
assertThat(title).isNotNull();
assertThat(title.getText().toString()).isEqualTo(
mParent.getString(R.string.audio_sharing_retry_dialog_title));
} }
@Test @Test

View File

@@ -120,9 +120,9 @@ public class AudioSharingIncompatibleDialogFragmentTest {
assertThat(dialog.isShowing()).isTrue(); assertThat(dialog.isShowing()).isTrue();
TextView title = dialog.findViewById(R.id.title_text); TextView title = dialog.findViewById(R.id.title_text);
assertThat(title).isNotNull(); assertThat(title).isNotNull();
// TODO: use string res
assertThat(title.getText().toString()).isEqualTo( assertThat(title.getText().toString()).isEqualTo(
"Can't share audio with " + TEST_DEVICE_NAME); mParent.getString(R.string.audio_sharing_incompatible_dialog_title,
TEST_DEVICE_NAME));
} }
@Test @Test

View File

@@ -629,8 +629,8 @@ public class AudioSharingSwitchBarControllerTest {
AudioSharingProgressDialogFragment.class.getName()); AudioSharingProgressDialogFragment.class.getName());
AudioSharingProgressDialogFragment progressFragment = AudioSharingProgressDialogFragment progressFragment =
(AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments); (AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments);
// TODO: use string res once finalized String expectedMessage = mContext.getString(
String expectedMessage = "Starting audio stream..."; R.string.audio_sharing_progress_dialog_start_stream_content);
checkProgressDialogMessage(progressFragment, expectedMessage); checkProgressDialogMessage(progressFragment, expectedMessage);
when(mBroadcast.isEnabled(null)).thenReturn(true); when(mBroadcast.isEnabled(null)).thenReturn(true);
@@ -640,8 +640,8 @@ public class AudioSharingSwitchBarControllerTest {
verify(mFeatureFactory.metricsFeatureProvider) verify(mFeatureFactory.metricsFeatureProvider)
.action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING)); .action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING));
// TODO: use string res once finalized expectedMessage = mContext.getString(
expectedMessage = "Sharing with " + TEST_DEVICE_NAME2 + "..."; R.string.audio_sharing_progress_dialog_add_source_content, TEST_DEVICE_NAME2);
checkProgressDialogMessage(progressFragment, expectedMessage); checkProgressDialogMessage(progressFragment, expectedMessage);
childFragments = mParentFragment.getChildFragmentManager().getFragments(); childFragments = mParentFragment.getChildFragmentManager().getFragments();
@@ -714,8 +714,8 @@ public class AudioSharingSwitchBarControllerTest {
AudioSharingProgressDialogFragment.class.getName()); AudioSharingProgressDialogFragment.class.getName());
AudioSharingProgressDialogFragment progressFragment = AudioSharingProgressDialogFragment progressFragment =
(AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments); (AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments);
// TODO: use string res once finalized String expectedMessage = mContext.getString(
String expectedMessage = "Sharing with " + TEST_DEVICE_NAME1 + "..."; R.string.audio_sharing_progress_dialog_add_source_content, TEST_DEVICE_NAME1);
checkProgressDialogMessage(progressFragment, expectedMessage); checkProgressDialogMessage(progressFragment, expectedMessage);
childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss()); childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
@@ -755,8 +755,8 @@ public class AudioSharingSwitchBarControllerTest {
AudioSharingProgressDialogFragment.class.getName()); AudioSharingProgressDialogFragment.class.getName());
AudioSharingProgressDialogFragment progressFragment = AudioSharingProgressDialogFragment progressFragment =
(AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments); (AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments);
// TODO: use string res once finalized String expectedMessage = mContext.getString(
String expectedMessage = "Sharing with " + TEST_DEVICE_NAME2 + "..."; R.string.audio_sharing_progress_dialog_add_source_content, TEST_DEVICE_NAME2);
checkProgressDialogMessage(progressFragment, expectedMessage); checkProgressDialogMessage(progressFragment, expectedMessage);
childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss()); childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
@@ -1027,8 +1027,8 @@ public class AudioSharingSwitchBarControllerTest {
// Progress dialog shows sharing progress for the auto add second sink. // Progress dialog shows sharing progress for the auto add second sink.
AudioSharingProgressDialogFragment progressFragment = AudioSharingProgressDialogFragment progressFragment =
(AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments); (AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments);
// TODO: use string res once finalized String expectedMessage = mContext.getString(
String expectedMessage = "Sharing with " + TEST_DEVICE_NAME1 + "..."; R.string.audio_sharing_progress_dialog_add_source_content, TEST_DEVICE_NAME1);
checkProgressDialogMessage(progressFragment, expectedMessage); checkProgressDialogMessage(progressFragment, expectedMessage);
childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss()); childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());

View File

@@ -34,6 +34,8 @@ import android.os.UserHandle;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.R;
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;
@@ -153,6 +155,12 @@ public class AutoTimePreferenceControllerTest {
assertThat(mController.isEnabled()).isFalse(); assertThat(mController.isEnabled()).isFalse();
} }
@Test
public void getSummary() {
assertThat(mController.getSummary().toString()).isEqualTo(
mContext.getString(R.string.date_time_auto_summary));
}
private static TimeCapabilitiesAndConfig createCapabilitiesAndConfig(boolean autoSupported, private static TimeCapabilitiesAndConfig createCapabilitiesAndConfig(boolean autoSupported,
boolean autoEnabled) { boolean autoEnabled) {
int configureAutoDetectionEnabledCapability = int configureAutoDetectionEnabledCapability =

View File

@@ -225,7 +225,8 @@ public class AutoTimeZonePreferenceControllerTest {
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
when(mTimeManager.updateTimeZoneConfiguration(Mockito.any())).thenReturn(true); when(mTimeManager.updateTimeZoneConfiguration(Mockito.any())).thenReturn(true);
assertThat(mController.getSummary()).isEqualTo(""); assertThat(mController.getSummary().toString()).isEqualTo(
mContext.getString(R.string.zone_auto_title_summary));
capabilitiesAndConfig = createCapabilitiesAndConfig( capabilitiesAndConfig = createCapabilitiesAndConfig(
/* autoSupported= */true, /* autoEnabled= */true, /* telephonySupported= */ /* autoSupported= */true, /* autoEnabled= */true, /* telephonySupported= */
@@ -233,7 +234,7 @@ public class AutoTimeZonePreferenceControllerTest {
when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
when(mTimeManager.updateTimeZoneConfiguration(Mockito.any())).thenReturn(true); when(mTimeManager.updateTimeZoneConfiguration(Mockito.any())).thenReturn(true);
assertThat(mController.getSummary()).isEqualTo( assertThat(mController.getSummary().toString()).isEqualTo(
mContext.getString(R.string.auto_zone_requires_location_summary)); mContext.getString(R.string.auto_zone_requires_location_summary));
} }

View File

@@ -41,6 +41,7 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers; import org.robolectric.util.ReflectionHelpers;
// LINT.IfChange
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class FirmwareVersionDetailPreferenceControllerTest { public class FirmwareVersionDetailPreferenceControllerTest {
@@ -112,3 +113,4 @@ public class FirmwareVersionDetailPreferenceControllerTest {
} }
} }
} }
// LINT.ThenChange(FirmwareVersionDetailPreferenceTest.kt)

View File

@@ -0,0 +1,76 @@
/*
* 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.deviceinfo.firmwareversion
import android.content.Context
import android.content.ContextWrapper
import android.os.Build
import android.os.SystemClock
import android.os.UserManager
import androidx.preference.Preference
import androidx.test.core.app.ApplicationProvider
import com.android.settings.deviceinfo.firmwareversion.FirmwareVersionDetailPreference.Companion.DELAY_TIMER_MILLIS
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.robolectric.RobolectricTestRunner
// LINT.IfChange
@RunWith(RobolectricTestRunner::class)
class FirmwareVersionDetailPreferenceTest {
private var userManager: UserManager? = null
private val context: Context =
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
override fun getSystemService(name: String): Any? =
if (name == Context.USER_SERVICE) userManager else super.getSystemService(name)
}
private val preference = Preference(context)
private val firmwareVersionDetailPreference = FirmwareVersionDetailPreference()
@Test
fun getSummary() {
assertThat(firmwareVersionDetailPreference.getSummary(context))
.isEqualTo(Build.VERSION.RELEASE_OR_PREVIEW_DISPLAY)
}
@Test
fun onPreferenceClick_hits() {
prepareClick()
assertThat(firmwareVersionDetailPreference.onPreferenceClick(preference)).isFalse()
}
@Test
fun onPreferenceClick_restricted() {
prepareClick()
userManager = mock { on { hasUserRestriction(UserManager.DISALLOW_FUN) } doReturn true }
assertThat(firmwareVersionDetailPreference.onPreferenceClick(preference)).isTrue()
}
private fun prepareClick() {
SystemClock.sleep(DELAY_TIMER_MILLIS + 1)
assertThat(SystemClock.uptimeMillis()).isGreaterThan(DELAY_TIMER_MILLIS)
for (i in 1..<FirmwareVersionDetailPreference.ACTIVITY_TRIGGER_COUNT) {
assertThat(firmwareVersionDetailPreference.onPreferenceClick(preference)).isTrue()
}
}
}
// LINT.ThenChange(FirmwareVersionDetailPreferenceControllerTest.java)

View File

@@ -45,6 +45,7 @@ import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
// LINT.IfChange
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class CopyrightPreferenceControllerTest { public class CopyrightPreferenceControllerTest {
@@ -119,3 +120,4 @@ public class CopyrightPreferenceControllerTest {
return testResolveInfo; return testResolveInfo;
} }
} }
// LINT.ThenChange(LegalPreferenceTest.kt)

View File

@@ -0,0 +1,92 @@
/*
* 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.deviceinfo.legal
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import androidx.test.core.app.ApplicationProvider
import com.android.settings.R
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub
import org.robolectric.RobolectricTestRunner
// LINT.IfChange
@RunWith(RobolectricTestRunner::class)
class LegalPreferenceTest {
private val pkgManager = mock<PackageManager>()
private val context: Context =
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
override fun getPackageManager(): PackageManager = pkgManager
}
private val copyrightPreference =
LegalPreference("copyright", R.string.copyright_title, "android.settings.COPYRIGHT")
@Test
fun isAvailable_systemApp_shouldReturnTrue() {
val testResolveInfos: MutableList<ResolveInfo> = ArrayList()
testResolveInfos.add(getTestResolveInfo(/* isSystemApp= */ true))
pkgManager.stub {
on { queryIntentActivities(any(Intent::class.java), anyInt()) } doReturn
testResolveInfos
}
assertThat(copyrightPreference.isAvailable(context)).isTrue()
}
@Test
fun isAvailable_nonSystemApp_shouldReturnFalse() {
val testResolveInfos: MutableList<ResolveInfo> = ArrayList()
testResolveInfos.add(getTestResolveInfo(/* isSystemApp= */ false))
pkgManager.stub {
on { queryIntentActivities(any(Intent::class.java), anyInt()) } doReturn
testResolveInfos
}
assertThat(copyrightPreference.isAvailable(context)).isFalse()
}
private fun getTestResolveInfo(isSystemApp: Boolean): ResolveInfo {
val testResolveInfo = ResolveInfo()
val testAppInfo = ApplicationInfo()
if (isSystemApp) {
testAppInfo.flags = testAppInfo.flags or ApplicationInfo.FLAG_SYSTEM
}
testResolveInfo.activityInfo =
ActivityInfo().apply {
name = "TestActivityName"
packageName = "TestPackageName"
applicationInfo = testAppInfo
}
return testResolveInfo
}
}
// LINT.ThenChange(CopyrightPreferenceControllerTest.java)

View File

@@ -0,0 +1,53 @@
/*
* 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.deviceinfo.legal
import android.content.Context
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
import android.text.TextUtils
import androidx.test.core.app.ApplicationProvider
import com.android.settings.flags.Flags
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class LegalSettingsScreenTest {
@get:Rule val setFlagsRule = SetFlagsRule()
private val context: Context = ApplicationProvider.getApplicationContext()
private val legalSettingsScreen = LegalSettingsScreen()
@Test
fun screenKey_exist() {
assertThat(TextUtils.equals(legalSettingsScreen.key, LegalSettingsScreen.KEY)).isTrue()
}
@Test
@EnableFlags(Flags.FLAG_CATALYST_LEGAL_INFORMATION)
fun isFlagEnabled_returnTrue() {
assertThat(legalSettingsScreen.isFlagEnabled(context)).isTrue()
}
@Test
@DisableFlags(Flags.FLAG_CATALYST_LEGAL_INFORMATION)
fun isFlagDisabled_returnTrue() {
assertThat(legalSettingsScreen.isFlagEnabled(context)).isFalse()
}
}

View File

@@ -45,6 +45,7 @@ import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
// LINT.IfChange
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class LicensePreferenceControllerTest { public class LicensePreferenceControllerTest {
@@ -119,3 +120,4 @@ public class LicensePreferenceControllerTest {
return testResolveInfo; return testResolveInfo;
} }
} }
// LINT.ThenChange(LegalPreferenceTest.kt)

View File

@@ -45,6 +45,7 @@ import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
// LINT.IfChange
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class TermsPreferenceControllerTest { public class TermsPreferenceControllerTest {
@@ -119,3 +120,4 @@ public class TermsPreferenceControllerTest {
return testResolveInfo; return testResolveInfo;
} }
} }
// LINT.ThenChange(LegalPreferenceTest.kt)

View File

@@ -29,6 +29,7 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
// LINT.IfChange
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class WallpaperAttributionsPreferenceControllerTest { public class WallpaperAttributionsPreferenceControllerTest {
@@ -55,3 +56,4 @@ public class WallpaperAttributionsPreferenceControllerTest {
.isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE); .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
} }
} }
// LINT.ThenChange(WallpaperAttributionsPreferenceTest.kt)

View File

@@ -0,0 +1,57 @@
/*
* 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.deviceinfo.legal
import android.content.Context
import android.content.ContextWrapper
import android.content.res.Resources
import androidx.test.core.app.ApplicationProvider
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub
import org.robolectric.RobolectricTestRunner
// LINT.IfChange
@RunWith(RobolectricTestRunner::class)
class WallpaperAttributionsPreferenceTest {
private val mockResources = mock<Resources>()
private val context: Context =
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
override fun getResources(): Resources = mockResources
}
private val wallpaperAttributionsPreference = WallpaperAttributionsPreference()
@Test
fun isAvailable_configTrue_shouldReturnTrue() {
mockResources.stub { on { getBoolean(anyInt()) } doReturn true }
assertThat(wallpaperAttributionsPreference.isAvailable(context)).isTrue()
}
@Test
fun isAvailable_configFalse_shouldReturnFalse() {
mockResources.stub { on { getBoolean(anyInt()) } doReturn false }
assertThat(wallpaperAttributionsPreference.isAvailable(context)).isFalse()
}
}
// LINT.ThenChange(WallpaperAttributionsPreferenceControllerTest.java)

View File

@@ -45,6 +45,7 @@ import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
// LINT.IfChange
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class WebViewLicensePreferenceControllerTest { public class WebViewLicensePreferenceControllerTest {
@@ -119,3 +120,4 @@ public class WebViewLicensePreferenceControllerTest {
return testResolveInfo; return testResolveInfo;
} }
} }
// LINT.ThenChange(LegalPreferenceTest.kt)

View File

@@ -0,0 +1,92 @@
/*
* 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.display;
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
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 android.content.Context;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import com.android.settings.accessibility.Flags;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
/**
* Tests for {@link AutoBrightnessPreferenceControllerForSetupWizard}.
*/
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {SettingsShadowResources.class})
public class AutoBrightnessPreferenceControllerForSetupWizardTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private static final String PREFERENCE_KEY = "auto_brightness";
private Context mContext;
private AutoBrightnessPreferenceControllerForSetupWizard mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController =
new AutoBrightnessPreferenceControllerForSetupWizard(mContext, PREFERENCE_KEY);
}
@Test
@EnableFlags(Flags.FLAG_ADD_BRIGHTNESS_SETTINGS_IN_SUW)
public void getAvailabilityStatus_configTrueAndFlagOn_shouldReturnAvailableUnsearchable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_automatic_brightness_available, true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
@Test
@EnableFlags(Flags.FLAG_ADD_BRIGHTNESS_SETTINGS_IN_SUW)
public void getAvailabilityStatus_configFalseSetAndFlagOn_shouldReturnUnsupportedOnDevice() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_automatic_brightness_available, false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
@DisableFlags(Flags.FLAG_ADD_BRIGHTNESS_SETTINGS_IN_SUW)
public void getAvailabilityStatus_flagOff_shouldReturnConditionallyUnavailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_automatic_brightness_available, true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
}

View File

@@ -21,24 +21,18 @@ import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL; import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE; import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings; import android.provider.Settings;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.accessibility.Flags;
import com.android.settings.testutils.shadow.SettingsShadowResources; import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
@@ -46,13 +40,13 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
/**
* Tests for {@link AutoBrightnessPreferenceController}.
*/
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = {SettingsShadowResources.class}) @Config(shadows = {SettingsShadowResources.class})
public class AutoBrightnessPreferenceControllerTest { public class AutoBrightnessPreferenceControllerTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private static final String PREFERENCE_KEY = "auto_brightness"; private static final String PREFERENCE_KEY = "auto_brightness";
private Context mContext; private Context mContext;
@@ -130,34 +124,13 @@ public class AutoBrightnessPreferenceControllerTest {
} }
@Test @Test
public void getAvailabilityStatusNotInSUW_configTrueSet_shouldReturnAvailableUnsearchable() { public void getAvailabilityStatus_configTrueSet_shouldReturnAvailableUnsearchable() {
SettingsShadowResources.overrideResource( SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_automatic_brightness_available, true); com.android.internal.R.bool.config_automatic_brightness_available, true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
} }
@Test
@EnableFlags(Flags.FLAG_ADD_BRIGHTNESS_SETTINGS_IN_SUW)
public void getAvailabilityStatusInSUW_configTrueAndFlagOn_shouldReturnAvailableUnsearchable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_automatic_brightness_available, true);
mController.setInSetupWizard(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
@Test
@DisableFlags(Flags.FLAG_ADD_BRIGHTNESS_SETTINGS_IN_SUW)
public void
getAvailabilityStatusInSUW_configTrueAndFlagOff_shouldReturnConditionallyUnavailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_automatic_brightness_available, true);
mController.setInSetupWizard(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test @Test
public void getAvailabilityStatus_configFalseSet_shouldReturnUnsupportedOnDevice() { public void getAvailabilityStatus_configFalseSet_shouldReturnUnsupportedOnDevice() {
SettingsShadowResources.overrideResource( SettingsShadowResources.overrideResource(

View File

@@ -0,0 +1,69 @@
/*
* 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.display;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import com.android.settings.accessibility.Flags;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
/**
* Tests for {@link BrightnessLevelPreferenceControllerForSetupWizard}.
*/
@RunWith(RobolectricTestRunner.class)
public class BrightnessLevelPreferenceControllerForSetupWizardTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private Context mContext;
private BrightnessLevelPreferenceControllerForSetupWizard mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new BrightnessLevelPreferenceControllerForSetupWizard(mContext,
/* lifecycle= */ null);
}
@Test
@EnableFlags(Flags.FLAG_ADD_BRIGHTNESS_SETTINGS_IN_SUW)
public void getAvailabilityStatus_flagOn_shouldReturnAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
@DisableFlags(Flags.FLAG_ADD_BRIGHTNESS_SETTINGS_IN_SUW)
public void getAvailabilityStatus_flagOff_shouldReturnConditionallyUnavailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
}

View File

@@ -33,9 +33,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.hardware.display.BrightnessInfo; import android.hardware.display.BrightnessInfo;
import android.os.PowerManager; import android.os.PowerManager;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings.System; import android.provider.Settings.System;
import android.view.Display; import android.view.Display;
@@ -43,12 +40,10 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.accessibility.Flags;
import com.android.settings.core.SettingsBaseActivity; import com.android.settings.core.SettingsBaseActivity;
import com.android.settingslib.transition.SettingsTransitionHelper; import com.android.settingslib.transition.SettingsTransitionHelper;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
@@ -61,12 +56,11 @@ import org.robolectric.shadows.ShadowActivity;
import org.robolectric.shadows.ShadowApplication; import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowContentResolver; import org.robolectric.shadows.ShadowContentResolver;
/**
* Tests for {@link BrightnessLevelPreferenceController}.
*/
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class BrightnessLevelPreferenceControllerTest { public class BrightnessLevelPreferenceControllerTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock @Mock
private PowerManager mPowerManager; private PowerManager mPowerManager;
@Mock @Mock
@@ -95,28 +89,14 @@ public class BrightnessLevelPreferenceControllerTest {
mPowerManager); mPowerManager);
when(mScreen.findPreference(anyString())).thenReturn(mPreference); when(mScreen.findPreference(anyString())).thenReturn(mPreference);
doReturn(mDisplay).when(mContext).getDisplay(); doReturn(mDisplay).when(mContext).getDisplay();
mController = spy(new BrightnessLevelPreferenceController(mContext, null)); mController = spy(new BrightnessLevelPreferenceController(mContext, /* lifecycle= */ null));
} }
@Test @Test
public void isAvailable_shouldAlwaysReturnTrueWhenNotInSetupWizard() { public void isAvailable_shouldAlwaysReturnTrue() {
assertThat(mController.isAvailable()).isTrue(); assertThat(mController.isAvailable()).isTrue();
} }
@Test
@EnableFlags(Flags.FLAG_ADD_BRIGHTNESS_SETTINGS_IN_SUW)
public void isAvailable_inSetupWizardAndFlagOn_shouldReturnTrue() {
mController.setInSetupWizard(true);
assertThat(mController.isAvailable()).isTrue();
}
@Test
@DisableFlags(Flags.FLAG_ADD_BRIGHTNESS_SETTINGS_IN_SUW)
public void isAvailable_inSetupWizardAndFlagOff_shouldReturnFalse() {
mController.setInSetupWizard(true);
assertThat(mController.isAvailable()).isFalse();
}
@Test @Test
public void onStart_shouldRegisterObserver() { public void onStart_shouldRegisterObserver() {
BrightnessLevelPreferenceController controller = BrightnessLevelPreferenceController controller =

View File

@@ -19,19 +19,16 @@ package com.android.settings.network.apn
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.hasScrollAction
import androidx.compose.ui.test.hasText import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onChild
import androidx.compose.ui.test.onChildAt
import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performScrollToNode import androidx.compose.ui.test.performScrollToNode
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R import com.android.settings.R
import com.google.common.truth.Truth import com.google.common.truth.Truth.assertThat
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -39,8 +36,7 @@ import org.mockito.kotlin.mock
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class ApnEditPageProviderTest { class ApnEditPageProviderTest {
@get:Rule @get:Rule val composeTestRule = createComposeRule()
val composeTestRule = createComposeRule()
private val context: Context = ApplicationProvider.getApplicationContext() private val context: Context = ApplicationProvider.getApplicationContext()
private val apnName = "apn_name" private val apnName = "apn_name"
@@ -51,86 +47,73 @@ class ApnEditPageProviderTest {
private val apnProtocolOptions = private val apnProtocolOptions =
context.resources.getStringArray(R.array.apn_protocol_entries).toList() context.resources.getStringArray(R.array.apn_protocol_entries).toList()
private val passwordTitle = context.resources.getString(R.string.apn_password) private val passwordTitle = context.resources.getString(R.string.apn_password)
private val apnInit = ApnData( private val apnInit =
ApnData(
name = apnName, name = apnName,
proxy = proxy, proxy = proxy,
port = port, port = port,
apnType = apnType, apnType = apnType,
apnRoaming = apnProtocolOptions.indexOf(apnRoaming), apnRoaming = apnProtocolOptions.indexOf(apnRoaming),
) )
private val apnData = mutableStateOf( private val apnData = mutableStateOf(apnInit)
apnInit
)
private val uri = mock<Uri> {} private val uri = mock<Uri> {}
@Test @Test
fun apnEditPageProvider_name() { fun apnEditPageProvider_name() {
Truth.assertThat(ApnEditPageProvider.name).isEqualTo("ApnEdit") assertThat(ApnEditPageProvider.name).isEqualTo("ApnEdit")
} }
@Test @Test
fun title_displayed() { fun title_displayed() {
composeTestRule.setContent { composeTestRule.setContent { ApnPage(apnInit, apnData, uri) }
ApnPage(apnInit, remember { apnData }, uri)
}
composeTestRule.onNodeWithText(context.getString(R.string.apn_edit)).assertIsDisplayed() composeTestRule.onNodeWithText(context.getString(R.string.apn_edit)).assertIsDisplayed()
} }
@Test @Test
fun name_displayed() { fun name_displayed() {
composeTestRule.setContent { composeTestRule.setContent { ApnPage(apnInit, apnData, uri) }
ApnPage(apnInit, remember { apnData }, uri)
}
composeTestRule.onNodeWithText(apnName, true).assertIsDisplayed() composeTestRule.onNodeWithText(apnName, true).assertIsDisplayed()
} }
@Test @Test
fun proxy_displayed() { fun proxy_displayed() {
composeTestRule.setContent { composeTestRule.setContent { ApnPage(apnInit, apnData, uri) }
ApnPage(apnInit, remember { apnData }, uri)
} composeTestRule.onNode(hasScrollAction()).performScrollToNode(hasText(proxy, true))
composeTestRule.onRoot().onChild().onChildAt(0)
.performScrollToNode(hasText(proxy, true))
composeTestRule.onNodeWithText(proxy, true).assertIsDisplayed() composeTestRule.onNodeWithText(proxy, true).assertIsDisplayed()
} }
@Test @Test
fun port_displayed() { fun port_displayed() {
composeTestRule.setContent { composeTestRule.setContent { ApnPage(apnInit, apnData, uri) }
ApnPage(apnInit, remember { apnData }, uri)
} composeTestRule.onNode(hasScrollAction()).performScrollToNode(hasText(port, true))
composeTestRule.onRoot().onChild().onChildAt(0)
.performScrollToNode(hasText(port, true))
composeTestRule.onNodeWithText(port, true).assertIsDisplayed() composeTestRule.onNodeWithText(port, true).assertIsDisplayed()
} }
@Test @Test
fun apn_type_displayed() { fun apnType_displayed() {
composeTestRule.setContent { composeTestRule.setContent { ApnPage(apnInit, apnData, uri) }
ApnPage(apnInit, remember { apnData }, uri)
} composeTestRule.onNode(hasScrollAction()).performScrollToNode(hasText(apnType, true))
composeTestRule.onRoot().onChild().onChildAt(0)
.performScrollToNode(hasText(apnType, true))
composeTestRule.onNodeWithText(apnType, true).assertIsDisplayed() composeTestRule.onNodeWithText(apnType, true).assertIsDisplayed()
} }
@Test @Test
fun apn_roaming_displayed() { fun apnRoaming_displayed() {
composeTestRule.setContent { composeTestRule.setContent { ApnPage(apnInit, apnData, uri) }
ApnPage(apnInit, remember { apnData }, uri)
} composeTestRule.onNode(hasScrollAction()).performScrollToNode(hasText(apnRoaming, true))
composeTestRule.onRoot().onChild().onChildAt(0)
.performScrollToNode(hasText(apnRoaming, true))
composeTestRule.onNodeWithText(apnRoaming, true).assertIsDisplayed() composeTestRule.onNodeWithText(apnRoaming, true).assertIsDisplayed()
} }
@Test @Test
fun password_displayed() { fun password_displayed() {
composeTestRule.setContent { composeTestRule.setContent { ApnPage(apnInit, apnData, uri) }
ApnPage(apnInit, remember { apnData }, uri)
} composeTestRule.onNode(hasScrollAction()).performScrollToNode(hasText(passwordTitle, true))
composeTestRule.onRoot().onChild().onChildAt(0)
.performScrollToNode(hasText(passwordTitle, true))
composeTestRule.onNodeWithText(passwordTitle, true).assertIsDisplayed() composeTestRule.onNodeWithText(passwordTitle, true).assertIsDisplayed()
} }
} }