Snap for 10580366 from baf2971e15
to udc-qpr1-release
Change-Id: I1a98617be33e6988cadc368e387499dff0106d05
This commit is contained in:
@@ -83,6 +83,7 @@ android_library {
|
||||
"net-utils-framework-common",
|
||||
"app-usage-event-protos-lite",
|
||||
"battery-event-protos-lite",
|
||||
"power-anomaly-event-protos-lite",
|
||||
"settings-contextual-card-protos-lite",
|
||||
"settings-log-bridge-protos-lite",
|
||||
"settings-telephony-protos-lite",
|
||||
|
@@ -611,23 +611,26 @@
|
||||
<item>3</item>
|
||||
</integer-array>
|
||||
|
||||
<!-- TODO(b/287448187): add USER_MIN_ASPECT_RATIO_DISPLAY_SIZE entry -->
|
||||
<!-- App screen size settings screen, User aspect ratio override options. Must be the same
|
||||
<!-- App aspect ratio settings screen, user aspect ratio override options. Must be the same
|
||||
length and order as config_userAspectRatioOverrideValues below. -->
|
||||
<string-array name="config_userAspectRatioOverrideEntries" translatable="false">
|
||||
<item>@string/user_aspect_ratio_app_default</item>
|
||||
<item>@string/user_aspect_ratio_fullscreen</item>
|
||||
<item>@string/user_aspect_ratio_half_screen</item>
|
||||
<item>@string/user_aspect_ratio_device_size</item>
|
||||
<item>@string/user_aspect_ratio_16_9</item>
|
||||
<item>@string/user_aspect_ratio_4_3</item>
|
||||
<item>@string/user_aspect_ratio_3_2</item>
|
||||
</string-array>
|
||||
|
||||
<!-- App screen size settings screen, User aspect ratio override options. Must be the same
|
||||
<!-- App aspect ratio settings screen, user aspect ratio override options. Must be the same
|
||||
length and order as config_userAspectRatioOverrideEntries above. The values must
|
||||
correspond to PackageManager.UserMinAspectRatio -->
|
||||
<integer-array name="config_userAspectRatioOverrideValues" translatable="false">
|
||||
<item>0</item> <!-- USER_MIN_ASPECT_RATIO_UNSET -->
|
||||
<item>6</item> <!-- USER_MIN_ASPECT_RATIO_FULLSCREEN -->
|
||||
<item>1</item> <!-- USER_MIN_ASPECT_RATIO_SPLIT_SCREEN -->
|
||||
<item>2</item> <!-- USER_MIN_ASPECT_RATIO_DISPLAY_SIZE -->
|
||||
<item>4</item> <!-- USER_MIN_ASPECT_RATIO_16_9 -->
|
||||
<item>3</item> <!-- USER_MIN_ASPECT_RATIO_4_3 -->
|
||||
<item>5</item> <!-- USER_MIN_ASPECT_RATIO_3_2 -->
|
||||
|
@@ -12081,25 +12081,32 @@
|
||||
other {Apps installed more than # months ago}
|
||||
}</string>
|
||||
|
||||
<!-- App Screen Size (User Aspect Ratio Override) -->
|
||||
<!-- [CHAR LIMIT=60] Screen size app list title setting to choose aspect ratio -->
|
||||
<string name="screen_size_title">Screen size</string>
|
||||
<!-- [CHAR LIMIT=NONE] Screen size setting summary to choose aspect ratio for apps unoptimized for device -->
|
||||
<string name="screen_size_summary">Choose an aspect ratio for apps if they haven’t been optimized for your <xliff:g id="device_name">%1$s</xliff:g></string>
|
||||
<!-- App Aspect Ratio (User Aspect Ratio Override) -->
|
||||
<!-- [CHAR LIMIT=60] Aspect ratio title setting to choose app aspect ratio -->
|
||||
<string name="aspect_ratio_title">Aspect ratio</string>
|
||||
<!-- [CHAR LIMIT=NONE] Aspect ratio setting summary to choose aspect ratio for apps unoptimized for device -->
|
||||
<string name="aspect_ratio_summary">Choose an aspect ratio to view this app if it hasn\'t been designed to fit your <xliff:g id="device_name">%1$s</xliff:g></string>
|
||||
<!-- [CHAR LIMIT=NONE] Aspect ratio suggested apps filter label -->
|
||||
<string name="user_aspect_ratio_suggested_apps_label">Suggested apps</string>
|
||||
<!-- [CHAR LIMIT=NONE] Filter label for apps that have user aspect ratio override applied -->
|
||||
<string name="user_aspect_ratio_overridden_apps_label">Apps you have overridden</string>
|
||||
<!-- [CHAR LIMIT=NONE] App default aspect ratio entry -->
|
||||
<string name="user_aspect_ratio_app_default">App default</string>
|
||||
<!-- [CHAR LIMIT=NONE] Half-screen aspect ratio entry -->
|
||||
<string name="user_aspect_ratio_half_screen">Half-screen</string>
|
||||
<!-- [CHAR LIMIT=NONE] Fullscreen aspect ratio entry -->
|
||||
<string name="user_aspect_ratio_fullscreen">Full screen</string>
|
||||
<!-- [CHAR LIMIT=NONE] Half screen aspect ratio entry -->
|
||||
<string name="user_aspect_ratio_half_screen">Half screen</string>
|
||||
<!-- [CHAR LIMIT=NONE] Device display size aspect ratio entry -->
|
||||
<string name="user_aspect_ratio_device_size">Device aspect ratio</string>
|
||||
<!-- [CHAR LIMIT=NONE] 16:9 aspect ratio entry -->
|
||||
<string name="user_aspect_ratio_16_9">16:9</string>
|
||||
<!-- [CHAR LIMIT=NONE] 3:2 aspect ratio entry -->
|
||||
<string name="user_aspect_ratio_3_2">3:2</string>
|
||||
<!-- [CHAR LIMIT=NONE] 4:3 aspect ratio entry -->
|
||||
<string name="user_aspect_ratio_4_3">4:3</string>
|
||||
<!-- [CHAR LIMIT=NONE] Warning description for app info aspect ratio page -->
|
||||
<string name="app_aspect_ratio_footer">The app will restart when you change aspect ratio. You may lose unsaved changes.</string>
|
||||
|
||||
|
||||
<!-- Accessibility label for fingerprint sensor [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_fingerprint_label">Fingerprint sensor</string>
|
||||
|
@@ -81,7 +81,7 @@
|
||||
|
||||
<Preference
|
||||
android:key="aspect_ratio_apps"
|
||||
android:title="@string/screen_size_title"
|
||||
android:title="@string/aspect_ratio_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:order="14"
|
||||
settings:controller="com.android.settings.applications.appcompat.UserAspectRatioAppsPreferenceController"
|
||||
|
59
res/xml/user_aspect_ratio_details.xml
Normal file
59
res/xml/user_aspect_ratio_details.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2023 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/aspect_ratio_title">
|
||||
|
||||
<com.android.settingslib.widget.ActionButtonsPreference
|
||||
android:key="header_view" />
|
||||
|
||||
<com.android.settingslib.widget.SelectorWithWidgetPreference
|
||||
android:key="app_default_pref"
|
||||
android:title="@string/user_aspect_ratio_app_default"/>
|
||||
|
||||
<com.android.settingslib.widget.SelectorWithWidgetPreference
|
||||
android:key="fullscreen_pref"
|
||||
android:title="@string/user_aspect_ratio_fullscreen"/>
|
||||
|
||||
<com.android.settingslib.widget.SelectorWithWidgetPreference
|
||||
android:key="half_screen_pref"
|
||||
android:title="@string/user_aspect_ratio_half_screen"/>
|
||||
|
||||
<com.android.settingslib.widget.SelectorWithWidgetPreference
|
||||
android:key="display_size_pref"
|
||||
android:title="@string/user_aspect_ratio_device_size"/>
|
||||
|
||||
<com.android.settingslib.widget.SelectorWithWidgetPreference
|
||||
android:key="16_9_pref"
|
||||
android:title="@string/user_aspect_ratio_16_9"/>
|
||||
|
||||
<com.android.settingslib.widget.SelectorWithWidgetPreference
|
||||
android:key="4_3_pref"
|
||||
android:title="@string/user_aspect_ratio_4_3"/>
|
||||
|
||||
<com.android.settingslib.widget.SelectorWithWidgetPreference
|
||||
android:key="3_2_pref"
|
||||
android:title="@string/user_aspect_ratio_3_2"/>
|
||||
|
||||
<com.android.settingslib.widget.FooterPreference
|
||||
android:title="@string/app_aspect_ratio_footer"
|
||||
android:selectable="false"
|
||||
settings:searchable="false"/>
|
||||
|
||||
</PreferenceScreen>
|
@@ -43,6 +43,6 @@ public class UserAspectRatioAppsPreferenceController extends BasePreferenceContr
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
return mContext.getResources().getString(R.string.screen_size_summary, Build.MODEL);
|
||||
return mContext.getResources().getString(R.string.aspect_ratio_summary, Build.MODEL);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.appcompat;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_16_9;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_4_3;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_DISPLAY_SIZE;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.IActivityManager;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.AppInfoWithHeader;
|
||||
import com.android.settingslib.widget.ActionButtonsPreference;
|
||||
import com.android.settingslib.widget.SelectorWithWidgetPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* App specific activity to show aspect ratio overrides
|
||||
*/
|
||||
public class UserAspectRatioDetails extends AppInfoWithHeader implements
|
||||
SelectorWithWidgetPreference.OnClickListener {
|
||||
private static final String TAG = UserAspectRatioDetails.class.getSimpleName();
|
||||
|
||||
private static final String KEY_HEADER_BUTTONS = "header_view";
|
||||
private static final String KEY_PREF_FULLSCREEN = "fullscreen_pref";
|
||||
private static final String KEY_PREF_HALF_SCREEN = "half_screen_pref";
|
||||
private static final String KEY_PREF_DISPLAY_SIZE = "display_size_pref";
|
||||
private static final String KEY_PREF_16_9 = "16_9_pref";
|
||||
private static final String KEY_PREF_4_3 = "4_3_pref";
|
||||
@VisibleForTesting
|
||||
static final String KEY_PREF_DEFAULT = "app_default_pref";
|
||||
@VisibleForTesting
|
||||
static final String KEY_PREF_3_2 = "3_2_pref";
|
||||
|
||||
private final List<SelectorWithWidgetPreference> mAspectRatioPreferences = new ArrayList<>();
|
||||
|
||||
@NonNull private UserAspectRatioManager mUserAspectRatioManager;
|
||||
@NonNull private String mSelectedKey = KEY_PREF_DEFAULT;
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mUserAspectRatioManager = new UserAspectRatioManager(getContext());
|
||||
initPreferences();
|
||||
try {
|
||||
final int userAspectRatio = mUserAspectRatioManager
|
||||
.getUserMinAspectRatioValue(mPackageName, mUserId);
|
||||
mSelectedKey = getSelectedKey(userAspectRatio);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Unable to get user min aspect ratio");
|
||||
}
|
||||
refreshUi();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRadioButtonClicked(@NonNull SelectorWithWidgetPreference selected) {
|
||||
final String selectedKey = selected.getKey();
|
||||
if (mSelectedKey.equals(selectedKey)) {
|
||||
return;
|
||||
}
|
||||
final int userAspectRatio = getSelectedUserMinAspectRatio(selectedKey);
|
||||
try {
|
||||
getAspectRatioManager().setUserMinAspectRatio(mPackageName, mUserId, userAspectRatio);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Unable to set user min aspect ratio");
|
||||
return;
|
||||
}
|
||||
// Only update to selected aspect ratio if nothing goes wrong
|
||||
mSelectedKey = selectedKey;
|
||||
updateAllPreferences(mSelectedKey);
|
||||
Log.d(TAG, "Killing application process " + mPackageName);
|
||||
try {
|
||||
final IActivityManager am = ActivityManager.getService();
|
||||
am.stopAppForUser(mPackageName, mUserId);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Unable to stop application " + mPackageName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
// TODO(b/292566895): add metrics for logging
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean refreshUi() {
|
||||
if (mPackageInfo == null || mPackageInfo.applicationInfo == null) {
|
||||
return false;
|
||||
}
|
||||
updateAllPreferences(mSelectedKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AlertDialog createDialog(int id, int errorCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void launchApplication() {
|
||||
Intent launchIntent = mPm.getLaunchIntentForPackage(mPackageName)
|
||||
.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
|
||||
if (launchIntent != null) {
|
||||
getContext().startActivityAsUser(launchIntent, new UserHandle(mUserId));
|
||||
}
|
||||
}
|
||||
|
||||
@PackageManager.UserMinAspectRatio
|
||||
private int getSelectedUserMinAspectRatio(@NonNull String selectedKey) {
|
||||
switch (selectedKey) {
|
||||
case KEY_PREF_FULLSCREEN:
|
||||
return USER_MIN_ASPECT_RATIO_FULLSCREEN;
|
||||
case KEY_PREF_HALF_SCREEN:
|
||||
return USER_MIN_ASPECT_RATIO_SPLIT_SCREEN;
|
||||
case KEY_PREF_DISPLAY_SIZE:
|
||||
return USER_MIN_ASPECT_RATIO_DISPLAY_SIZE;
|
||||
case KEY_PREF_3_2:
|
||||
return USER_MIN_ASPECT_RATIO_3_2;
|
||||
case KEY_PREF_4_3:
|
||||
return USER_MIN_ASPECT_RATIO_4_3;
|
||||
case KEY_PREF_16_9:
|
||||
return USER_MIN_ASPECT_RATIO_16_9;
|
||||
default:
|
||||
return USER_MIN_ASPECT_RATIO_UNSET;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getSelectedKey(@PackageManager.UserMinAspectRatio int userMinAspectRatio) {
|
||||
switch (userMinAspectRatio) {
|
||||
case USER_MIN_ASPECT_RATIO_FULLSCREEN:
|
||||
return KEY_PREF_FULLSCREEN;
|
||||
case USER_MIN_ASPECT_RATIO_SPLIT_SCREEN:
|
||||
return KEY_PREF_HALF_SCREEN;
|
||||
case USER_MIN_ASPECT_RATIO_DISPLAY_SIZE:
|
||||
return KEY_PREF_DISPLAY_SIZE;
|
||||
case USER_MIN_ASPECT_RATIO_3_2:
|
||||
return KEY_PREF_3_2;
|
||||
case USER_MIN_ASPECT_RATIO_4_3:
|
||||
return KEY_PREF_4_3;
|
||||
case USER_MIN_ASPECT_RATIO_16_9:
|
||||
return KEY_PREF_16_9;
|
||||
default:
|
||||
return KEY_PREF_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
private void initPreferences() {
|
||||
addPreferencesFromResource(R.xml.user_aspect_ratio_details);
|
||||
|
||||
((ActionButtonsPreference) findPreference(KEY_HEADER_BUTTONS))
|
||||
.setButton1Text(R.string.launch_instant_app)
|
||||
.setButton1Icon(R.drawable.ic_settings_open)
|
||||
.setButton1OnClickListener(v -> launchApplication());
|
||||
|
||||
addPreference(KEY_PREF_DEFAULT, USER_MIN_ASPECT_RATIO_UNSET);
|
||||
addPreference(KEY_PREF_FULLSCREEN, USER_MIN_ASPECT_RATIO_FULLSCREEN);
|
||||
addPreference(KEY_PREF_DISPLAY_SIZE, USER_MIN_ASPECT_RATIO_DISPLAY_SIZE);
|
||||
addPreference(KEY_PREF_HALF_SCREEN, USER_MIN_ASPECT_RATIO_SPLIT_SCREEN);
|
||||
addPreference(KEY_PREF_16_9, USER_MIN_ASPECT_RATIO_16_9);
|
||||
addPreference(KEY_PREF_4_3, USER_MIN_ASPECT_RATIO_4_3);
|
||||
addPreference(KEY_PREF_3_2, USER_MIN_ASPECT_RATIO_3_2);
|
||||
}
|
||||
|
||||
private void addPreference(@NonNull String key,
|
||||
@PackageManager.UserMinAspectRatio int aspectRatio) {
|
||||
final SelectorWithWidgetPreference pref = findPreference(key);
|
||||
if (pref == null) {
|
||||
return;
|
||||
}
|
||||
if (!mUserAspectRatioManager.containsAspectRatioOption(aspectRatio)) {
|
||||
pref.setVisible(false);
|
||||
return;
|
||||
}
|
||||
pref.setTitle(mUserAspectRatioManager.getUserMinAspectRatioEntry(aspectRatio));
|
||||
pref.setOnClickListener(this);
|
||||
mAspectRatioPreferences.add(pref);
|
||||
}
|
||||
|
||||
private void updateAllPreferences(@NonNull String selectedKey) {
|
||||
for (SelectorWithWidgetPreference pref : mAspectRatioPreferences) {
|
||||
pref.setChecked(selectedKey.equals(pref.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
UserAspectRatioManager getAspectRatioManager() {
|
||||
return mUserAspectRatioManager;
|
||||
}
|
||||
}
|
@@ -28,6 +28,7 @@ import android.provider.DeviceConfig;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
@@ -49,6 +50,9 @@ public class UserAspectRatioManager {
|
||||
@VisibleForTesting
|
||||
static final String KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS =
|
||||
"enable_app_compat_user_aspect_ratio_settings";
|
||||
static final String KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN =
|
||||
"enable_app_compat_user_aspect_ratio_fullscreen";
|
||||
private static final boolean DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_FULLSCREEN = true;
|
||||
|
||||
private final Context mContext;
|
||||
private final IPackageManager mIPm;
|
||||
@@ -70,7 +74,8 @@ public class UserAspectRatioManager {
|
||||
public static boolean isFeatureEnabled(Context context) {
|
||||
final boolean isBuildTimeFlagEnabled = context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_appCompatUserAppAspectRatioSettingsIsEnabled);
|
||||
return isBuildTimeFlagEnabled && getValueFromDeviceConfig();
|
||||
return getValueFromDeviceConfig(KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS,
|
||||
DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_SETTINGS) && isBuildTimeFlagEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +84,9 @@ public class UserAspectRatioManager {
|
||||
@PackageManager.UserMinAspectRatio
|
||||
public int getUserMinAspectRatioValue(@NonNull String packageName, int uid)
|
||||
throws RemoteException {
|
||||
return mIPm.getUserMinAspectRatio(packageName, uid);
|
||||
final int aspectRatio = mIPm.getUserMinAspectRatio(packageName, uid);
|
||||
return containsAspectRatioOption(aspectRatio)
|
||||
? aspectRatio : PackageManager.USER_MIN_ASPECT_RATIO_UNSET;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,8 +94,41 @@ public class UserAspectRatioManager {
|
||||
*/
|
||||
@NonNull
|
||||
public String getUserMinAspectRatioEntry(@PackageManager.UserMinAspectRatio int aspectRatio) {
|
||||
return mUserAspectRatioMap.getOrDefault(
|
||||
aspectRatio, mContext.getString(R.string.user_aspect_ratio_app_default));
|
||||
if (!containsAspectRatioOption(aspectRatio)) {
|
||||
return mUserAspectRatioMap.get(PackageManager.USER_MIN_ASPECT_RATIO_UNSET);
|
||||
}
|
||||
return mUserAspectRatioMap.get(aspectRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return corresponding aspect ratio string for package name and user
|
||||
*/
|
||||
@NonNull
|
||||
public String getUserMinAspectRatioEntry(@NonNull String packageName, int uid)
|
||||
throws RemoteException {
|
||||
final int aspectRatio = getUserMinAspectRatioValue(packageName, uid);
|
||||
return getUserMinAspectRatioEntry(aspectRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether user aspect ratio option is specified in
|
||||
* {@link R.array.config_userAspectRatioOverrideValues}
|
||||
* and is enabled by device config
|
||||
*/
|
||||
public boolean containsAspectRatioOption(@PackageManager.UserMinAspectRatio int option) {
|
||||
if (option == PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN
|
||||
&& !isFullscreenOptionEnabled()) {
|
||||
return false;
|
||||
}
|
||||
return mUserAspectRatioMap.containsKey(option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets user-specified {@link PackageManager.UserMinAspectRatio} override for an app
|
||||
*/
|
||||
public void setUserMinAspectRatio(@NonNull String packageName, int uid,
|
||||
@PackageManager.UserMinAspectRatio int aspectRatio) throws RemoteException {
|
||||
mIPm.setUserMinAspectRatio(packageName, uid, aspectRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,11 +141,20 @@ public class UserAspectRatioManager {
|
||||
return hasLauncherEntry;
|
||||
}
|
||||
|
||||
private static boolean getValueFromDeviceConfig() {
|
||||
return DeviceConfig.getBoolean(
|
||||
DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||
KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS,
|
||||
DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_SETTINGS);
|
||||
/**
|
||||
* Whether fullscreen option in per-app user aspect ratio settings is enabled
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean isFullscreenOptionEnabled() {
|
||||
final boolean isBuildTimeFlagEnabled = mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_appCompatUserAppAspectRatioFullscreenIsEnabled);
|
||||
return isBuildTimeFlagEnabled && getValueFromDeviceConfig(
|
||||
KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN,
|
||||
DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_FULLSCREEN);
|
||||
}
|
||||
|
||||
private static boolean getValueFromDeviceConfig(String name, boolean defaultValue) {
|
||||
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER, name, defaultValue);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -122,14 +171,18 @@ public class UserAspectRatioManager {
|
||||
final Map<Integer, String> userMinAspectRatioMap = new ArrayMap<>();
|
||||
for (int i = 0; i < userMinAspectRatioValues.length; i++) {
|
||||
final int aspectRatioVal = userMinAspectRatioValues[i];
|
||||
final String aspectRatioString = getAspectRatioStringOrDefault(
|
||||
userMinAspectRatioStrings[i], aspectRatioVal);
|
||||
switch (aspectRatioVal) {
|
||||
// Only map known values of UserMinAspectRatio and ignore unknown entries
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN:
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_UNSET:
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN:
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_DISPLAY_SIZE:
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_4_3:
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_16_9:
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_3_2:
|
||||
userMinAspectRatioMap.put(aspectRatioVal, userMinAspectRatioStrings[i]);
|
||||
userMinAspectRatioMap.put(aspectRatioVal, aspectRatioString);
|
||||
}
|
||||
}
|
||||
if (!userMinAspectRatioMap.containsKey(PackageManager.USER_MIN_ASPECT_RATIO_UNSET)) {
|
||||
@@ -139,6 +192,31 @@ public class UserAspectRatioManager {
|
||||
return userMinAspectRatioMap;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getAspectRatioStringOrDefault(@Nullable String aspectRatioString,
|
||||
@PackageManager.UserMinAspectRatio int aspectRatioVal) {
|
||||
if (aspectRatioString != null) {
|
||||
return aspectRatioString;
|
||||
}
|
||||
// Options are customized per device and if strings are set to @null, use default
|
||||
switch (aspectRatioVal) {
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN:
|
||||
return mContext.getString(R.string.user_aspect_ratio_fullscreen);
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN:
|
||||
return mContext.getString(R.string.user_aspect_ratio_half_screen);
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_DISPLAY_SIZE:
|
||||
return mContext.getString(R.string.user_aspect_ratio_device_size);
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_4_3:
|
||||
return mContext.getString(R.string.user_aspect_ratio_4_3);
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_16_9:
|
||||
return mContext.getString(R.string.user_aspect_ratio_16_9);
|
||||
case PackageManager.USER_MIN_ASPECT_RATIO_3_2:
|
||||
return mContext.getString(R.string.user_aspect_ratio_3_2);
|
||||
default:
|
||||
return mContext.getString(R.string.user_aspect_ratio_app_default);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void addInfoHasLauncherEntry(@NonNull ResolveInfo infoHasLauncherEntry) {
|
||||
mInfoHasLauncherEntryList.add(infoHasLauncherEntry);
|
||||
|
@@ -50,7 +50,7 @@ public class WhenToDreamPicker extends RadioButtonPickerFragment {
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.DREAM;
|
||||
return SettingsEnums.SETTINGS_WHEN_TO_DREAM;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -18,6 +18,7 @@ package com.android.settings.fuelgauge;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
@@ -129,9 +130,14 @@ public interface PowerUsageFeatureProvider {
|
||||
boolean delayHourlyJobWhenBooting();
|
||||
|
||||
/**
|
||||
* Insert device usage data for anomaly detection
|
||||
* Insert settings configuration data for anomaly detection
|
||||
*/
|
||||
void insertSettingsData(Context context);
|
||||
void insertSettingsData(Context context, double displayDrain);
|
||||
|
||||
/**
|
||||
* Returns {@link Bundle} for settings anomaly detection result
|
||||
*/
|
||||
Bundle detectSettingsAnomaly(Context context, double displayDrain);
|
||||
|
||||
/**
|
||||
* Gets an intent for one time bypass charge limited to resume charging.
|
||||
|
@@ -21,6 +21,7 @@ import static com.android.settings.Utils.SYSTEMUI_PACKAGE_NAME;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
@@ -161,7 +162,12 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertSettingsData(Context context) {}
|
||||
public void insertSettingsData(Context context, double displayDrain) {}
|
||||
|
||||
@Override
|
||||
public Bundle detectSettingsAnomaly(Context context, double displayDrain) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Integer> getOthersSystemComponentSet() {
|
||||
|
@@ -18,6 +18,7 @@ package com.android.settings.fuelgauge;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.os.BatteryManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@@ -139,7 +140,10 @@ public class TopLevelBatteryPreferenceController extends BasePreferenceControlle
|
||||
if (Utils.containsIncompatibleChargers(mContext, TAG)) {
|
||||
return mContext.getString(R.string.battery_info_status_not_charging);
|
||||
}
|
||||
if (!info.discharging && info.chargeLabel != null) {
|
||||
if (info.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
|
||||
// Present status only if no remaining time or status anomalous
|
||||
return info.statusLabel;
|
||||
} else if (!info.discharging && info.chargeLabel != null) {
|
||||
return info.chargeLabel;
|
||||
} else if (info.remainingLabel == null) {
|
||||
return info.batteryPercentString;
|
||||
|
@@ -30,3 +30,11 @@ java_library {
|
||||
},
|
||||
srcs: ["fuelgauge_usage_state.proto"],
|
||||
}
|
||||
|
||||
java_library {
|
||||
name: "power-anomaly-event-protos-lite",
|
||||
proto: {
|
||||
type: "lite",
|
||||
},
|
||||
srcs: ["power_anomaly_event.proto"],
|
||||
}
|
||||
|
@@ -0,0 +1,37 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option java_multiple_files = true;
|
||||
option java_package = "com.android.settings.fuelgauge.batteryusage";
|
||||
option java_outer_classname = "PowerAnomalyEventProto";
|
||||
|
||||
message PowerAnomalyEvent {
|
||||
optional int64 timestamp = 1;
|
||||
optional string type = 2; // e.g. settings, apps
|
||||
optional string key = 3; // e.g. brightness, significant_increase
|
||||
optional float score = 4;
|
||||
oneof info {
|
||||
WarningBannerInfo warning_banner_info = 5;
|
||||
WarningItemInfo warning_item_info = 6;
|
||||
}
|
||||
}
|
||||
|
||||
message WarningBannerInfo {
|
||||
optional string title_string = 1;
|
||||
optional string description_string = 2;
|
||||
optional string main_button_string = 3;
|
||||
optional string main_button_action = 4;
|
||||
optional string cancel_button_string = 5;
|
||||
optional string cancel_button_action = 6;
|
||||
}
|
||||
|
||||
message WarningItemInfo {
|
||||
optional int64 start_timestamp = 1;
|
||||
optional int64 end_timestamp = 2;
|
||||
optional string top_card_string = 3;
|
||||
optional string title_string = 4;
|
||||
optional string description_string = 5;
|
||||
optional string main_button_string = 6;
|
||||
optional string main_button_action = 7;
|
||||
optional string cancel_button_string = 8;
|
||||
optional string cancel_button_action = 9;
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.spa.app.appcompat
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.android.settings.R
|
||||
import com.android.settings.applications.appcompat.UserAspectRatioDetails
|
||||
import com.android.settings.applications.appcompat.UserAspectRatioManager
|
||||
import com.android.settings.applications.appinfo.AppInfoDashboardFragment
|
||||
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
|
||||
@OptIn(ExperimentalLifecycleComposeApi::class)
|
||||
@Composable
|
||||
fun UserAspectRatioAppPreference(app: ApplicationInfo) {
|
||||
val context = LocalContext.current
|
||||
val presenter = remember { UserAspectRatioAppPresenter(context, app) }
|
||||
if (!presenter.isAvailableFlow.collectAsStateWithLifecycle(initialValue = false).value) return
|
||||
|
||||
Preference(object : PreferenceModel {
|
||||
override val title = stringResource(R.string.aspect_ratio_title)
|
||||
override val summary = presenter.summaryFlow.collectAsStateWithLifecycle(
|
||||
initialValue = stringResource(R.string.summary_placeholder),
|
||||
)
|
||||
override val onClick = presenter::startActivity
|
||||
})
|
||||
}
|
||||
|
||||
class UserAspectRatioAppPresenter(
|
||||
private val context: Context,
|
||||
private val app: ApplicationInfo,
|
||||
) {
|
||||
private val manager = UserAspectRatioManager(context)
|
||||
|
||||
val isAvailableFlow = flow {
|
||||
emit(UserAspectRatioManager.isFeatureEnabled(context)
|
||||
&& manager.canDisplayAspectRatioUi(app))
|
||||
}.flowOn(Dispatchers.IO)
|
||||
|
||||
fun startActivity() =
|
||||
navigateToAppAspectRatioSettings(context, app)
|
||||
|
||||
val summaryFlow = flow {
|
||||
emit(manager.getUserMinAspectRatioEntry(app.packageName, context.userId))
|
||||
}.flowOn(Dispatchers.IO)
|
||||
}
|
||||
|
||||
fun navigateToAppAspectRatioSettings(context: Context, app: ApplicationInfo) {
|
||||
AppInfoDashboardFragment.startAppInfoFragment(
|
||||
UserAspectRatioDetails::class.java,
|
||||
app,
|
||||
context,
|
||||
AppInfoSettingsProvider.METRICS_CATEGORY,
|
||||
)
|
||||
}
|
@@ -36,7 +36,6 @@ import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.android.settings.R
|
||||
import com.android.settings.applications.appcompat.UserAspectRatioManager
|
||||
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
|
||||
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
|
||||
@@ -81,7 +80,7 @@ object UserAspectRatioAppsPageProvider : SettingsPageProvider {
|
||||
@VisibleForTesting
|
||||
fun EntryItem() =
|
||||
Preference(object : PreferenceModel {
|
||||
override val title = stringResource(R.string.screen_size_title)
|
||||
override val title = stringResource(R.string.aspect_ratio_title)
|
||||
override val summary = getSummary().toState()
|
||||
override val onClick = navigator(name)
|
||||
})
|
||||
@@ -94,7 +93,7 @@ object UserAspectRatioAppsPageProvider : SettingsPageProvider {
|
||||
|
||||
@Composable
|
||||
@VisibleForTesting
|
||||
fun getSummary(): String = stringResource(R.string.screen_size_summary, Build.MODEL)
|
||||
fun getSummary(): String = stringResource(R.string.aspect_ratio_summary, Build.MODEL)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -103,7 +102,7 @@ fun UserAspectRatioAppList(
|
||||
= { AppList() },
|
||||
) {
|
||||
AppListPage(
|
||||
title = stringResource(R.string.screen_size_title),
|
||||
title = stringResource(R.string.aspect_ratio_title),
|
||||
listModel = rememberContext(::UserAspectRatioAppListModel),
|
||||
appList = appList,
|
||||
header = {
|
||||
@@ -148,7 +147,7 @@ class UserAspectRatioAppListModel(private val context: Context)
|
||||
override fun AppListItemModel<UserAspectRatioAppListItemModel>.AppItem() {
|
||||
val app = record.app
|
||||
AppListItem(
|
||||
onClick = AppInfoSettingsProvider.navigator(app)
|
||||
onClick = { navigateToAppAspectRatioSettings(context, app) }
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,7 @@ import com.android.settings.R
|
||||
import com.android.settings.applications.AppInfoBase
|
||||
import com.android.settings.applications.appinfo.AppInfoDashboardFragment
|
||||
import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
|
||||
import com.android.settings.spa.app.appcompat.UserAspectRatioAppPreference
|
||||
import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider
|
||||
import com.android.settings.spa.app.specialaccess.DisplayOverOtherAppsAppListProvider
|
||||
import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider
|
||||
@@ -150,6 +151,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
|
||||
}
|
||||
|
||||
Category(title = stringResource(R.string.advanced_apps)) {
|
||||
UserAspectRatioAppPreference(app)
|
||||
DisplayOverOtherAppsAppListProvider.InfoPageEntryItem(app)
|
||||
ModifySystemSettingsAppListProvider.InfoPageEntryItem(app)
|
||||
PictureInPictureListProvider.InfoPageEntryItem(app)
|
||||
|
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.appcompat;
|
||||
|
||||
import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_3_2;
|
||||
import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_DEFAULT;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.IActivityManager;
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.testutils.shadow.ShadowActivityManager;
|
||||
import com.android.settingslib.widget.SelectorWithWidgetPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
/**
|
||||
* To run test: atest SettingsRoboTests:UserAspectRatioDetailsTest
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowActivityManager.class})
|
||||
public class UserAspectRatioDetailsTest {
|
||||
|
||||
@Mock
|
||||
private UserAspectRatioManager mUserAspectRatioManager;
|
||||
@Mock
|
||||
private IActivityManager mAm;
|
||||
|
||||
private SelectorWithWidgetPreference mRadioButtonPref;
|
||||
private Context mContext;
|
||||
private UserAspectRatioDetails mFragment;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mFragment = spy(new UserAspectRatioDetails());
|
||||
when(mFragment.getContext()).thenReturn(mContext);
|
||||
when(mFragment.getAspectRatioManager()).thenReturn(mUserAspectRatioManager);
|
||||
ShadowActivityManager.setService(mAm);
|
||||
mRadioButtonPref = new SelectorWithWidgetPreference(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRadioButtonClicked_prefChange_shouldStopActivity() throws RemoteException {
|
||||
// Default was already selected
|
||||
mRadioButtonPref.setKey(KEY_PREF_DEFAULT);
|
||||
mFragment.onRadioButtonClicked(mRadioButtonPref);
|
||||
// Preference changed
|
||||
mRadioButtonPref.setKey(KEY_PREF_3_2);
|
||||
mFragment.onRadioButtonClicked(mRadioButtonPref);
|
||||
// Only triggered once when preference change
|
||||
verify(mAm).stopAppForUser(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRadioButtonClicked_prefChange_shouldSetAspectRatio() throws RemoteException {
|
||||
// Default was already selected
|
||||
mRadioButtonPref.setKey(KEY_PREF_DEFAULT);
|
||||
mFragment.onRadioButtonClicked(mRadioButtonPref);
|
||||
// Preference changed
|
||||
mRadioButtonPref.setKey(KEY_PREF_3_2);
|
||||
mFragment.onRadioButtonClicked(mRadioButtonPref);
|
||||
// Only triggered once when preference changes
|
||||
verify(mUserAspectRatioManager).setUserMinAspectRatio(
|
||||
any(), anyInt(), anyInt());
|
||||
}
|
||||
}
|
@@ -31,6 +31,7 @@ import android.content.Intent;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.hardware.usb.UsbPort;
|
||||
import android.hardware.usb.UsbPortStatus;
|
||||
import android.os.BatteryManager;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
@@ -145,6 +146,17 @@ public class TopLevelBatteryPreferenceControllerTest {
|
||||
.isEqualTo(mContext.getString(R.string.battery_info_status_not_charging));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDashboardLabel_notChargingState_returnsCorrectLabel() {
|
||||
mController.mPreference = new Preference(mContext);
|
||||
BatteryInfo info = new BatteryInfo();
|
||||
info.batteryStatus = BatteryManager.BATTERY_STATUS_NOT_CHARGING;
|
||||
info.statusLabel = "expected returned label";
|
||||
|
||||
assertThat(mController.getDashboardLabel(mContext, info, true))
|
||||
.isEqualTo(info.statusLabel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_batteryNotPresent_shouldShowWarningMessage() {
|
||||
mController.mIsBatteryPresent = false;
|
||||
|
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.spa.app.appcompat
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.ResolveInfo
|
||||
import android.os.Build
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.assertIsEnabled
|
||||
import androidx.compose.ui.test.assertIsNotDisplayed
|
||||
import androidx.compose.ui.test.hasTextExactly
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onRoot
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito
|
||||
import android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER
|
||||
import com.android.settings.R
|
||||
import com.android.settings.applications.appinfo.AppInfoDashboardFragment
|
||||
import com.android.settings.applications.appcompat.UserAspectRatioDetails
|
||||
import com.android.settings.applications.appcompat.UserAspectRatioManager
|
||||
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
|
||||
import com.android.settings.testutils.TestDeviceConfig
|
||||
import com.android.settingslib.spa.testutils.delay
|
||||
import com.android.settingslib.spa.testutils.waitUntilExists
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.any
|
||||
import org.mockito.Mockito.anyInt
|
||||
import org.mockito.Mockito.eq
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.MockitoSession
|
||||
import org.mockito.Spy
|
||||
import org.mockito.quality.Strictness
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
/**
|
||||
* To run this test: atest SettingsSpaUnitTests:UserAspectRatioAppPreferenceTest
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class UserAspectRatioAppPreferenceTest {
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
|
||||
private lateinit var mockSession: MockitoSession
|
||||
|
||||
@Spy
|
||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
|
||||
@Spy
|
||||
private val resources = context.resources
|
||||
|
||||
private val aspectRatioEnabledConfig =
|
||||
TestDeviceConfig(NAMESPACE_WINDOW_MANAGER, "enable_app_compat_user_aspect_ratio_settings")
|
||||
|
||||
private lateinit var userAspectRatioManager: UserAspectRatioManager
|
||||
|
||||
@Mock
|
||||
private lateinit var packageManager: PackageManager
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
mockSession = ExtendedMockito.mockitoSession()
|
||||
.initMocks(this)
|
||||
.mockStatic(UserAspectRatioDetails::class.java)
|
||||
.mockStatic(AppInfoDashboardFragment::class.java)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.startMocking()
|
||||
whenever(context.resources).thenReturn(resources)
|
||||
whenever(context.packageManager).thenReturn(packageManager)
|
||||
userAspectRatioManager = mock(UserAspectRatioManager::class.java)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
aspectRatioEnabledConfig.reset()
|
||||
mockSession.finishMocking()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenConfigIsFalse_notDisplayed() {
|
||||
setConfig(false)
|
||||
|
||||
setContent()
|
||||
|
||||
composeTestRule.onRoot().assertIsNotDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCannotDisplayAspectRatioUi_notDisplayed() {
|
||||
setContent()
|
||||
|
||||
composeTestRule.onRoot().assertIsNotDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCanDisplayAspectRatioUiAndConfigFalse_notDisplayed() {
|
||||
setConfig(false)
|
||||
whenever(packageManager.queryIntentActivities(any(), anyInt()))
|
||||
.thenReturn(listOf(RESOLVE_INFO))
|
||||
|
||||
setContent()
|
||||
|
||||
composeTestRule.onRoot().assertIsNotDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCannotDisplayAspectRatioUiAndConfigTrue_notDisplayed() {
|
||||
setConfig(true)
|
||||
|
||||
setContent()
|
||||
|
||||
composeTestRule.onRoot().assertIsNotDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCanDisplayAspectRatioUiAndConfigTrue_Displayed() {
|
||||
setConfig(true)
|
||||
whenever(packageManager.queryIntentActivities(any(), anyInt()))
|
||||
.thenReturn(listOf(RESOLVE_INFO))
|
||||
|
||||
setContent()
|
||||
|
||||
composeTestRule.onNode(
|
||||
hasTextExactly(
|
||||
context.getString(R.string.aspect_ratio_title),
|
||||
context.getString(R.string.user_aspect_ratio_app_default)
|
||||
),
|
||||
).assertIsDisplayed().assertIsEnabled()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onClick_startActivity() {
|
||||
setConfig(true)
|
||||
whenever(packageManager.queryIntentActivities(any(), anyInt()))
|
||||
.thenReturn(listOf(RESOLVE_INFO))
|
||||
|
||||
setContent()
|
||||
composeTestRule.onRoot().performClick()
|
||||
|
||||
ExtendedMockito.verify {
|
||||
AppInfoDashboardFragment.startAppInfoFragment(
|
||||
UserAspectRatioDetails::class.java,
|
||||
APP,
|
||||
context,
|
||||
AppInfoSettingsProvider.METRICS_CATEGORY,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setConfig(enabled: Boolean) {
|
||||
whenever(resources.getBoolean(
|
||||
com.android.internal.R.bool.config_appCompatUserAppAspectRatioSettingsIsEnabled
|
||||
)).thenReturn(enabled)
|
||||
aspectRatioEnabledConfig.override(enabled)
|
||||
}
|
||||
|
||||
private fun setContent() {
|
||||
composeTestRule.setContent {
|
||||
CompositionLocalProvider(LocalContext provides context) {
|
||||
UserAspectRatioAppPreference(APP)
|
||||
}
|
||||
}
|
||||
composeTestRule.delay()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val PACKAGE_NAME = "package.name"
|
||||
const val UID = 123
|
||||
val APP = ApplicationInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
uid = UID
|
||||
}
|
||||
private val RESOLVE_INFO = ResolveInfo().apply {
|
||||
activityInfo = ActivityInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -60,21 +60,21 @@ class UserAspectRatioAppsPageProviderTest {
|
||||
@Test
|
||||
fun injectEntry_title() {
|
||||
setInjectEntry()
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.screen_size_title))
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.aspect_ratio_title))
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun injectEntry_summary() {
|
||||
setInjectEntry()
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.screen_size_summary, Build.MODEL))
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.aspect_ratio_summary, Build.MODEL))
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun injectEntry_onClick_navigate() {
|
||||
setInjectEntry()
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.screen_size_title)).performClick()
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.aspect_ratio_title)).performClick()
|
||||
assertThat(fakeNavControllerWrapper.navigateCalledWith).isEqualTo("UserAspectRatioAppsPage")
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ class UserAspectRatioAppsPageProviderTest {
|
||||
UserAspectRatioAppList {}
|
||||
}
|
||||
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.screen_size_title))
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.aspect_ratio_title))
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
|
||||
|
@@ -19,9 +19,11 @@ package com.android.settings.applications.appcompat;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_16_9;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_4_3;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN;
|
||||
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET;
|
||||
|
||||
import static com.android.settings.applications.appcompat.UserAspectRatioManager.KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN;
|
||||
import static com.android.settings.applications.appcompat.UserAspectRatioManager.KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@@ -30,16 +32,19 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.provider.DeviceConfig;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -54,21 +59,35 @@ import org.junit.runner.RunWith;
|
||||
public class UserAspectRatioManagerTest {
|
||||
|
||||
private Context mContext;
|
||||
private Resources mResources;
|
||||
private UserAspectRatioManager mUtils;
|
||||
private String mOriginalFlag;
|
||||
private String mOriginalSettingsFlag;
|
||||
private String mOriginalFullscreenFlag;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mResources = spy(mContext.getResources());
|
||||
mUtils = spy(new UserAspectRatioManager(mContext));
|
||||
mOriginalFlag = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||
KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS);
|
||||
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
|
||||
mOriginalSettingsFlag = DeviceConfig.getProperty(
|
||||
DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS);
|
||||
setAspectRatioSettingsBuildTimeFlagEnabled(true);
|
||||
setAspectRatioSettingsDeviceConfigEnabled("true" /* enabled */, false /* makeDefault */);
|
||||
|
||||
mOriginalFullscreenFlag = DeviceConfig.getProperty(
|
||||
DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN);
|
||||
setAspectRatioFullscreenBuildTimeFlagEnabled(true);
|
||||
setAspectRatioFullscreenDeviceConfigEnabled("true" /* enabled */, false /* makeDefault */);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||
KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS, mOriginalFlag, true /* makeDefault */);
|
||||
setAspectRatioSettingsDeviceConfigEnabled(mOriginalSettingsFlag, true /* makeDefault */);
|
||||
setAspectRatioFullscreenDeviceConfigEnabled(mOriginalFullscreenFlag,
|
||||
true /* makeDefault */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -87,13 +106,52 @@ public class UserAspectRatioManagerTest {
|
||||
|
||||
@Test
|
||||
public void testIsFeatureEnabled() {
|
||||
assertFalse(UserAspectRatioManager.isFeatureEnabled(mContext));
|
||||
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||
KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS, "true", false /* makeDefault */);
|
||||
assertTrue(UserAspectRatioManager.isFeatureEnabled(mContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFeatureEnabled_disabledBuildTimeFlag_returnFalse() {
|
||||
setAspectRatioSettingsBuildTimeFlagEnabled(false);
|
||||
assertFalse(UserAspectRatioManager.isFeatureEnabled(mContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFeatureEnabled_disabledRuntimeFlag_returnFalse() {
|
||||
setAspectRatioSettingsDeviceConfigEnabled("false" /* enabled */, false /* makeDefault */);
|
||||
assertFalse(UserAspectRatioManager.isFeatureEnabled(mContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFullscreenOptionEnabled() {
|
||||
assertTrue(mUtils.isFullscreenOptionEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFullscreenOptionEnabled_settingsDisabled_returnFalse() {
|
||||
setAspectRatioFullscreenBuildTimeFlagEnabled(false);
|
||||
assertFalse(mUtils.isFullscreenOptionEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFullscreenOptionEnabled_disabledBuildTimeFlag_returnFalse() {
|
||||
setAspectRatioFullscreenBuildTimeFlagEnabled(false);
|
||||
assertFalse(mUtils.isFullscreenOptionEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFullscreenOptionEnabled_disabledRuntimeFlag_returnFalse() {
|
||||
setAspectRatioFullscreenDeviceConfigEnabled("false" /* enabled */, false /*makeDefault */);
|
||||
assertFalse(mUtils.isFullscreenOptionEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void containsAspectRatioOption_fullscreen() {
|
||||
assertTrue(mUtils.containsAspectRatioOption(USER_MIN_ASPECT_RATIO_FULLSCREEN));
|
||||
|
||||
when(mUtils.isFullscreenOptionEnabled()).thenReturn(false);
|
||||
assertFalse(mUtils.containsAspectRatioOption(USER_MIN_ASPECT_RATIO_FULLSCREEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserMinAspectRatioEntry() {
|
||||
// R.string.user_aspect_ratio_app_default
|
||||
@@ -117,6 +175,38 @@ public class UserAspectRatioManagerTest {
|
||||
// R.string.user_aspect_ratio_16_9
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_16_9))
|
||||
.isEqualTo(ResourcesUtils.getResourcesString(mContext, "user_aspect_ratio_16_9"));
|
||||
// R.string.user_aspect_ratio_fullscreen
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN))
|
||||
.isEqualTo(ResourcesUtils.getResourcesString(mContext,
|
||||
"user_aspect_ratio_fullscreen"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserMinAspectRatioEntry_fullscreenDisabled_shouldReturnDefault() {
|
||||
setAspectRatioFullscreenBuildTimeFlagEnabled(false);
|
||||
assertThat(mUtils.getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN))
|
||||
.isEqualTo(ResourcesUtils.getResourcesString(mContext,
|
||||
"user_aspect_ratio_app_default"));
|
||||
}
|
||||
|
||||
private void setAspectRatioSettingsBuildTimeFlagEnabled(boolean enabled) {
|
||||
when(mResources.getBoolean(R.bool.config_appCompatUserAppAspectRatioSettingsIsEnabled))
|
||||
.thenReturn(enabled);
|
||||
}
|
||||
|
||||
private void setAspectRatioSettingsDeviceConfigEnabled(String enabled, boolean makeDefault) {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||
KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS, enabled, makeDefault);
|
||||
}
|
||||
|
||||
private void setAspectRatioFullscreenBuildTimeFlagEnabled(boolean enabled) {
|
||||
when(mResources.getBoolean(R.bool.config_appCompatUserAppAspectRatioFullscreenIsEnabled))
|
||||
.thenReturn(enabled);
|
||||
}
|
||||
|
||||
private void setAspectRatioFullscreenDeviceConfigEnabled(String enabled, boolean makeDefault) {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||
KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN, enabled, makeDefault);
|
||||
}
|
||||
|
||||
private void addResolveInfoLauncherEntry(String packageName) {
|
||||
|
Reference in New Issue
Block a user