diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 1855a6639e1..e368d09c3dc 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1314,7 +1314,7 @@ diff --git a/color-check-baseline.xml b/color-check-baseline.xml index 684a038dc85..88d0ab01dcc 100644 --- a/color-check-baseline.xml +++ b/color-check-baseline.xml @@ -61,6 +61,22 @@ column="5"/> + + + + + + + + - - - - - - - - - - - - @@ -169,7 +153,23 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + @@ -185,7 +185,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -201,7 +201,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -217,7 +217,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -233,23 +233,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - @@ -265,23 +249,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - @@ -297,23 +265,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - @@ -329,23 +281,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - @@ -361,7 +297,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -373,11 +309,11 @@ priority="4" summary="Using hardcoded color" explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes. This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app." - errorLine1=" <color name="fingerprint_enrollment_finish_color_outline">#669df6</color>" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" <color name="settings_dialog_colorError">#f28b82</color> <!-- Red 300 -->" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -393,7 +329,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -409,7 +345,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -425,7 +361,23 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + @@ -441,7 +393,23 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + @@ -457,7 +425,39 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + + + + + @@ -473,7 +473,23 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + @@ -489,7 +505,55 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + + + + + + + + + @@ -505,7 +569,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -521,7 +585,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -537,7 +601,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -553,7 +617,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -569,7 +633,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -585,7 +649,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -601,7 +665,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -617,7 +681,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -633,7 +697,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -649,7 +713,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -665,7 +729,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -681,7 +745,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -697,7 +761,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -713,7 +777,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -729,7 +793,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -745,7 +809,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -761,7 +825,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -777,7 +841,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -793,7 +857,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -809,7 +873,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -825,7 +889,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -841,7 +905,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -857,7 +921,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -873,7 +937,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -889,7 +953,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -905,7 +969,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -921,7 +985,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -937,55 +1001,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - @@ -1001,7 +1017,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1017,7 +1033,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1033,7 +1049,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1049,7 +1065,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1065,7 +1081,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1081,7 +1097,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1097,7 +1113,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1113,7 +1129,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1129,7 +1145,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1145,7 +1161,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1161,7 +1177,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1177,7 +1193,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1193,7 +1209,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1209,7 +1225,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1225,7 +1241,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1241,7 +1257,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1257,7 +1273,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1273,103 +1289,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - @@ -1385,7 +1305,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1401,7 +1321,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1417,7 +1337,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1433,7 +1353,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1449,7 +1369,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1465,7 +1385,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1481,7 +1401,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1497,7 +1417,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1513,7 +1433,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1529,7 +1449,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1545,7 +1465,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1561,7 +1481,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1577,7 +1497,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1593,7 +1513,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1609,7 +1529,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1625,7 +1545,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1641,7 +1561,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1657,7 +1577,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1673,7 +1593,71 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + + + + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index ee261362f7d..c0abada7377 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2435,6 +2435,8 @@ 1440p QHD+ Full resolution uses more of your battery. Switching your resolution may cause some apps to restart. + + Selected Colors @@ -2929,13 +2931,13 @@ Format SD card for internal storage - Store apps \u0026 media to use on this tablet only. <a href="https://support.google.com/android/answer/12153449">Learn more about setting up an SD card</a> + Store apps \u0026 media to use on this tablet only. <a href="https://support.google.com/android/answer/12153449">Learn more about setting up an SD card</a>. Format Format SD card for internal storage - Store apps \u0026 media to use on this phone only. <a href="https://support.google.com/android/answer/12153449">Learn more about setting up an SD card</a> + Store apps \u0026 media to use on this phone only. <a href="https://support.google.com/android/answer/12153449">Learn more about setting up an SD card</a>. Format @@ -2943,7 +2945,7 @@ Format SD card for portable storage - Store photos, videos, music, and more and access them from other devices. <a href="https://support.google.com/android/answer/12153449">Learn more about setting up an SD card</a> + Store photos, videos, music, and more and access them from other devices. <a href="https://support.google.com/android/answer/12153449">Learn more about setting up an SD card</a>. Format diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index 07388fd7422..8baac63c5dd 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -283,7 +283,7 @@ public class ManageApplications extends InstrumentedFragment final String className = getClassName(activity.getIntent(), getArguments()); if (className.equals(ManageExternalSourcesActivity.class.getName())) { SpaActivity.startSpaActivity( - context, InstallUnknownAppsListProvider.INSTANCE.getRoute()); + context, InstallUnknownAppsListProvider.INSTANCE.getAppListRoute()); activity.finish(); } } diff --git a/src/com/android/settings/display/ScreenResolutionFragment.java b/src/com/android/settings/display/ScreenResolutionFragment.java index b9777032004..b42dbe2c7e9 100644 --- a/src/com/android/settings/display/ScreenResolutionFragment.java +++ b/src/com/android/settings/display/ScreenResolutionFragment.java @@ -29,6 +29,8 @@ import android.hardware.display.DisplayManager; import android.provider.Settings; import android.text.TextUtils; import android.view.Display; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import androidx.annotation.VisibleForTesting; import androidx.preference.PreferenceScreen; @@ -65,6 +67,7 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment { private IllustrationPreference mImagePreference; private DisplayObserver mDisplayObserver; + private AccessibilityManager mAccessibilityManager; @Override public void onAttach(Context context) { @@ -72,6 +75,7 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment { mDefaultDisplay = context.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY); + mAccessibilityManager = context.getSystemService(AccessibilityManager.class); mResources = context.getResources(); mScreenResolutionOptions = mResources.getStringArray(R.array.config_screen_resolution_options_strings); @@ -215,6 +219,14 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment { if (!mDisplayObserver.setPendingResolutionChange(selectedWidth)) { return; } + + if (mAccessibilityManager.isEnabled()) { + AccessibilityEvent event = AccessibilityEvent.obtain(); + event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT); + event.getText().add(mResources.getString(R.string.screen_resolution_selected_a11y)); + mAccessibilityManager.sendAccessibilityEvent(event); + } + super.onRadioButtonClicked(selected); } diff --git a/src/com/android/settings/spa/SpaEnvironment.kt b/src/com/android/settings/spa/SpaEnvironment.kt index ad9999ae9c9..4d2e3e22d91 100644 --- a/src/com/android/settings/spa/SpaEnvironment.kt +++ b/src/com/android/settings/spa/SpaEnvironment.kt @@ -17,6 +17,8 @@ package com.android.settings.spa import com.android.settings.spa.app.AppsMainPageProvider +import com.android.settings.spa.app.appsettings.AppSettingsProvider +import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider import com.android.settings.spa.app.specialaccess.AllFilesAccessAppListProvider import com.android.settings.spa.app.specialaccess.DisplayOverOtherAppsAppListProvider import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider @@ -42,14 +44,16 @@ object SpaEnvironment { DisplayOverOtherAppsAppListProvider, MediaManagementAppsAppListProvider, ModifySystemSettingsAppListProvider, - InstallUnknownAppsListProvider, PictureInPictureListProvider, + InstallUnknownAppsListProvider, + AlarmsAndRemindersAppListProvider, ), ) SettingsPageProviderRepository( allPageProviders = listOf( HomePageProvider, AppsMainPageProvider, + AppSettingsProvider, SpecialAppAccessPageProvider, NotificationMainPageProvider, AppListNotificationsPageProvider, diff --git a/src/com/android/settings/spa/app/appsettings/AppSettings.kt b/src/com/android/settings/spa/app/appsettings/AppSettings.kt new file mode 100644 index 00000000000..d0a230f1ddd --- /dev/null +++ b/src/com/android/settings/spa/app/appsettings/AppSettings.kt @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 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.spa.app.appsettings + +import android.content.pm.ApplicationInfo +import android.content.pm.PackageInfo +import android.os.Bundle +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.res.stringResource +import androidx.navigation.NavType +import androidx.navigation.navArgument +import com.android.settings.R +import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider +import com.android.settings.spa.app.specialaccess.DisplayOverOtherAppsAppListProvider +import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider +import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListProvider +import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider +import com.android.settingslib.spa.framework.common.SettingsPageProvider +import com.android.settingslib.spa.framework.compose.navigator +import com.android.settingslib.spa.widget.scaffold.RegularScaffold +import com.android.settingslib.spa.widget.ui.Category +import com.android.settingslib.spaprivileged.model.app.PackageManagers +import com.android.settingslib.spaprivileged.model.app.toRoute +import com.android.settingslib.spaprivileged.template.app.AppInfoProvider + +private const val PACKAGE_NAME = "packageName" +private const val USER_ID = "userId" + +object AppSettingsProvider : SettingsPageProvider { + override val name = "AppSettings" + + override val parameter = listOf( + navArgument(PACKAGE_NAME) { type = NavType.StringType }, + navArgument(USER_ID) { type = NavType.IntType }, + ) + + @Composable + override fun Page(arguments: Bundle?) { + val packageName = arguments!!.getString(PACKAGE_NAME)!! + val userId = arguments.getInt(USER_ID) + remember { PackageManagers.getPackageInfoAsUser(packageName, userId) }?.let { + AppSettings(it) + } + } + + @Composable + fun navigator(app: ApplicationInfo) = navigator(route = "$name/${app.toRoute()}") +} + +@Composable +private fun AppSettings(packageInfo: PackageInfo) { + RegularScaffold(title = stringResource(R.string.application_info_label)) { + val appInfoProvider = remember { AppInfoProvider(packageInfo) } + + appInfoProvider.AppInfo() + + Category(title = stringResource(R.string.advanced_apps)) { + val app = packageInfo.applicationInfo + DisplayOverOtherAppsAppListProvider.InfoPageEntryItem(app) + ModifySystemSettingsAppListProvider.InfoPageEntryItem(app) + PictureInPictureListProvider.InfoPageEntryItem(app) + InstallUnknownAppsListProvider.InfoPageEntryItem(app) + // TODO: interact_across_profiles + AlarmsAndRemindersAppListProvider.InfoPageEntryItem(app) + } + + // TODO: app_installer + appInfoProvider.FooterAppVersion() + } +} diff --git a/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersAppList.kt b/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersAppList.kt new file mode 100644 index 00000000000..2439c20a19f --- /dev/null +++ b/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersAppList.kt @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2022 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.spa.app.specialaccess + +import android.Manifest +import android.app.AlarmManager +import android.app.compat.CompatChanges +import android.content.Context +import android.content.pm.ApplicationInfo +import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState +import com.android.settings.R +import com.android.settingslib.spaprivileged.model.app.AppRecord +import com.android.settingslib.spaprivileged.model.app.PackageManagers +import com.android.settingslib.spaprivileged.model.app.PackageManagers.hasRequestPermission +import com.android.settingslib.spaprivileged.model.app.userHandle +import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListModel +import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map + +object AlarmsAndRemindersAppListProvider : TogglePermissionAppListProvider { + override val permissionType = "AlarmsAndReminders" + override fun createModel(context: Context) = AlarmsAndRemindersAppListModel(context) +} + +data class AlarmsAndRemindersAppRecord( + override val app: ApplicationInfo, + val isChangeable: Boolean, + var controller: AlarmsAndRemindersController, +) : AppRecord + +class AlarmsAndRemindersAppListModel( + private val context: Context, +) : TogglePermissionAppListModel { + override val pageTitleResId = R.string.alarms_and_reminders_title + override val switchTitleResId = R.string.alarms_and_reminders_switch_title + override val footerResId = R.string.alarms_and_reminders_footer_title + + override fun transform(userIdFlow: Flow, appListFlow: Flow>) = + userIdFlow.map { userId -> + PackageManagers.getAppOpPermissionPackages(userId, PERMISSION) + }.combine(appListFlow) { packageNames, appList -> + appList.map { app -> + createRecord(app = app, hasRequestPermission = app.packageName in packageNames) + } + } + + override fun transformItem(app: ApplicationInfo) = + createRecord(app = app, hasRequestPermission = app.hasRequestPermission(PERMISSION)) + + override fun filter( + userIdFlow: Flow, + recordListFlow: Flow>, + ) = recordListFlow.map { recordList -> + recordList.filter { it.isChangeable } + } + + @Composable + override fun isAllowed(record: AlarmsAndRemindersAppRecord) = + record.controller.isAllowed.observeAsState() + + override fun isChangeable(record: AlarmsAndRemindersAppRecord) = record.isChangeable + + override fun setAllowed(record: AlarmsAndRemindersAppRecord, newAllowed: Boolean) { + record.controller.setAllowed(newAllowed) + } + + private fun createRecord(app: ApplicationInfo, hasRequestPermission: Boolean) = + AlarmsAndRemindersAppRecord( + app = app, + isChangeable = hasRequestPermission && app.isChangeEnabled(), + controller = AlarmsAndRemindersController(context, app), + ) + + companion object { + private const val PERMISSION: String = Manifest.permission.SCHEDULE_EXACT_ALARM + + private fun ApplicationInfo.isChangeEnabled(): Boolean = + CompatChanges.isChangeEnabled( + AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, packageName, userHandle, + ) + } +} diff --git a/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersController.kt b/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersController.kt new file mode 100644 index 00000000000..c83e20bf8b1 --- /dev/null +++ b/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersController.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2022 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.spa.app.specialaccess + +import android.app.AlarmManager +import android.app.AppOpsManager +import android.app.AppOpsManager.MODE_ALLOWED +import android.app.AppOpsManager.MODE_ERRORED +import android.content.Context +import android.content.pm.ApplicationInfo +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.android.settingslib.spaprivileged.model.app.userId + +class AlarmsAndRemindersController( + context: Context, + private val app: ApplicationInfo, +) { + private val alarmManager = context.getSystemService(AlarmManager::class.java)!! + private val appOpsManager = context.getSystemService(AppOpsManager::class.java)!! + + val isAllowed: LiveData + get() = _allowed + + fun setAllowed(allowed: Boolean) { + val mode = if (allowed) MODE_ALLOWED else MODE_ERRORED + appOpsManager.setUidMode(AppOpsManager.OPSTR_SCHEDULE_EXACT_ALARM, app.uid, mode) + _allowed.postValue(allowed) + } + + private val _allowed = object : MutableLiveData() { + override fun onActive() { + postValue(alarmManager.hasScheduleExactAlarm(app.packageName, app.userId)) + } + + override fun onInactive() { + } + } +} diff --git a/src/com/android/settings/spa/app/specialaccess/SpecialAppAccess.kt b/src/com/android/settings/spa/app/specialaccess/SpecialAppAccess.kt index 7ab1db77750..11abdfc5818 100644 --- a/src/com/android/settings/spa/app/specialaccess/SpecialAppAccess.kt +++ b/src/com/android/settings/spa/app/specialaccess/SpecialAppAccess.kt @@ -34,7 +34,11 @@ object SpecialAppAccessPageProvider : SettingsPageProvider { @Composable override fun Page(arguments: Bundle?) { - SpecialAppAccessPage() + RegularScaffold(title = stringResource(R.string.special_access)) { + for (entry in buildEntry(arguments)) { + entry.UiLayout() + } + } } @Composable @@ -51,26 +55,12 @@ object SpecialAppAccessPageProvider : SettingsPageProvider { override fun buildEntry(arguments: Bundle?): List { val owner = SettingsPage.create(name, parameter, arguments) return listOf( - AllFilesAccessAppListProvider.buildInjectEntry().setLink(fromPage = owner).build(), - DisplayOverOtherAppsAppListProvider.buildInjectEntry() - .setLink(fromPage = owner).build(), - MediaManagementAppsAppListProvider.buildInjectEntry().setLink(fromPage = owner).build(), - ModifySystemSettingsAppListProvider.buildInjectEntry() - .setLink(fromPage = owner).build(), - PictureInPictureListProvider.buildInjectEntry().setLink(fromPage = owner).build(), - InstallUnknownAppsListProvider.buildInjectEntry().setLink(fromPage = owner).build(), - ) - } -} - -@Composable -private fun SpecialAppAccessPage() { - RegularScaffold(title = stringResource(R.string.special_access)) { - AllFilesAccessAppListProvider.EntryItem() - DisplayOverOtherAppsAppListProvider.EntryItem() - MediaManagementAppsAppListProvider.EntryItem() - ModifySystemSettingsAppListProvider.EntryItem() - PictureInPictureListProvider.EntryItem() - InstallUnknownAppsListProvider.EntryItem() + AllFilesAccessAppListProvider, + DisplayOverOtherAppsAppListProvider, + MediaManagementAppsAppListProvider, + ModifySystemSettingsAppListProvider, + PictureInPictureListProvider, + InstallUnknownAppsListProvider, + ).map { it.buildAppListInjectEntry().setLink(fromPage = owner).build() } } }