diff --git a/res-product/values/strings.xml b/res-product/values/strings.xml
index c8ec5bd29a6..d549d668f4e 100644
--- a/res-product/values/strings.xml
+++ b/res-product/values/strings.xml
@@ -234,11 +234,11 @@
Device protection features won\u2019t be turned on. You won\u2019t be able to prevent others from using this phone if it\u2019s lost or stolen.
- The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen.
+ The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.
- The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen.
+ The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.
- The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen.
+ The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.
Now you can use your fingerprint to unlock your tablet or verify it\u2019s you, like when you sign in to apps or approve a purchase
diff --git a/res/drawable/ic_settings_battery_usage_others.xml b/res/drawable/ic_settings_battery_usage_others.xml
new file mode 100644
index 00000000000..a7abfe0615d
--- /dev/null
+++ b/res/drawable/ic_settings_battery_usage_others.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
diff --git a/res/values/config.xml b/res/values/config.xml
index db62b186f86..0c610e3a6a9 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -578,7 +578,13 @@
- @string/screen_resolution_option_high
- - @string/screen_resolution_option_full
+ - @string/screen_resolution_option_highest
+
+
+
+
+ - @string/screen_resolution_summary_high
+ - @string/screen_resolution_summary_highest
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0dc78dc3d1f..53b560af75e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -826,12 +826,6 @@
How to set up your fingerprint
It\u2019s on the back of your phone. Use your index finger.
-
- The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.
-
- The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.
-
- The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.
The fingerprint sensor is on your screen. You\u2019ll capture your fingerprint on the next screen.
@@ -2142,10 +2136,14 @@
Screen resolution
-
+
High resolution
-
- Full resolution
+
+ Full resolution
+
+ 1080p FHD+
+
+ 1440p QHD+
Full resolution uses more of your battery. Switching your resolution may cause some apps to restart.
diff --git a/src/com/android/settings/biometrics/BiometricEnrollSidecar.java b/src/com/android/settings/biometrics/BiometricEnrollSidecar.java
index 9a89f7a349f..97d46a420e3 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollSidecar.java
@@ -45,6 +45,14 @@ public abstract class BiometricEnrollSidecar extends InstrumentedFragment {
* @param isAcquiredGood whether the fingerprint image was good.
*/
default void onAcquired(boolean isAcquiredGood) { }
+ /**
+ * Called when a pointer down event has occurred.
+ */
+ default void onPointerDown(int sensorId) { }
+ /**
+ * Called when a pointer up event has occurred.
+ */
+ default void onPointerUp(int sensorId) { }
}
private int mEnrollmentSteps = -1;
@@ -118,6 +126,32 @@ public abstract class BiometricEnrollSidecar extends InstrumentedFragment {
}
}
+ private class QueuedPointerDown extends QueuedEvent {
+ private final int sensorId;
+
+ public QueuedPointerDown(int sensorId) {
+ this.sensorId = sensorId;
+ }
+
+ @Override
+ public void send(Listener listener) {
+ listener.onPointerDown(sensorId);
+ }
+ }
+
+ private class QueuedPointerUp extends QueuedEvent {
+ private final int sensorId;
+
+ public QueuedPointerUp(int sensorId) {
+ this.sensorId = sensorId;
+ }
+
+ @Override
+ public void send(Listener listener) {
+ listener.onPointerUp(sensorId);
+ }
+ }
+
private final Runnable mTimeoutRunnable = new Runnable() {
@Override
public void run() {
@@ -215,6 +249,22 @@ public abstract class BiometricEnrollSidecar extends InstrumentedFragment {
}
}
+ protected void onPointerDown(int sensorId) {
+ if (mListener != null) {
+ mListener.onPointerDown(sensorId);
+ } else {
+ mQueuedEvents.add(new QueuedPointerDown(sensorId));
+ }
+ }
+
+ protected void onPointerUp(int sensorId) {
+ if (mListener != null) {
+ mListener.onPointerUp(sensorId);
+ } else {
+ mQueuedEvents.add(new QueuedPointerUp(sensorId));
+ }
+ }
+
public void setListener(Listener listener) {
mListener = listener;
if (mListener != null) {
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index 60959e399a3..139a18fa376 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -82,6 +82,7 @@ import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieCompositionFactory;
import com.airbnb.lottie.LottieProperty;
import com.airbnb.lottie.model.KeyPath;
+import com.google.android.setupcompat.template.FooterActionButton;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -101,6 +102,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
private static final String TAG = "FingerprintEnrollEnrolling";
static final String TAG_SIDECAR = "sidecar";
+ static final String TAG_UDFPS_HELPER = "udfps_helper";
static final String KEY_STATE_CANCELED = "is_canceled";
static final String KEY_STATE_PREVIOUS_ROTATION = "previous_rotation";
@@ -353,6 +355,24 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
.build()
);
+ if (FeatureFlagUtils.isEnabled(getApplicationContext(),
+ FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) {
+ // Remove the space view and make the width of footer button container WRAP_CONTENT
+ // to avoid hiding the udfps view progress bar bottom.
+ final LinearLayout buttonContainer = mFooterBarMixin.getButtonContainer();
+ View spaceView = null;
+ for (int i = 0; i < buttonContainer.getChildCount(); i++) {
+ if (!(buttonContainer.getChildAt(i) instanceof FooterActionButton)) {
+ spaceView = buttonContainer.getChildAt(i);
+ break;
+ }
+ }
+ if (spaceView != null) {
+ spaceView.setVisibility(View.GONE);
+ buttonContainer.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
+ }
+ }
+
final LayerDrawable fingerprintDrawable = mProgressBar != null
? (LayerDrawable) mProgressBar.getBackground() : null;
if (fingerprintDrawable != null) {
@@ -867,6 +887,20 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
}
+ @Override
+ public void onPointerDown(int sensorId) {
+ if (mUdfpsEnrollHelper != null) {
+ mUdfpsEnrollHelper.onPointerDown(sensorId);
+ }
+ }
+
+ @Override
+ public void onPointerUp(int sensorId) {
+ if (mUdfpsEnrollHelper != null) {
+ mUdfpsEnrollHelper.onPointerUp(sensorId);
+ }
+ }
+
private void updateProgress(boolean animate) {
if (mSidecar == null || !mSidecar.isEnrolling()) {
Log.d(TAG, "Enrollment not started yet");
@@ -1195,7 +1229,16 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
udfpsProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
udfpsEnrollView.setOverlayParams(params);
- mUdfpsEnrollHelper = new UdfpsEnrollHelper(getApplicationContext(), mFingerprintManager);
+
+ mUdfpsEnrollHelper = (UdfpsEnrollHelper) getSupportFragmentManager().findFragmentByTag(
+ FingerprintEnrollEnrolling.TAG_UDFPS_HELPER);
+ if (mUdfpsEnrollHelper == null) {
+ mUdfpsEnrollHelper = new UdfpsEnrollHelper(getApplicationContext(),
+ mFingerprintManager);
+ getSupportFragmentManager().beginTransaction()
+ .add(mUdfpsEnrollHelper, FingerprintEnrollEnrolling.TAG_UDFPS_HELPER)
+ .commitAllowingStateLoss();
+ }
udfpsEnrollView.setEnrollHelper(mUdfpsEnrollHelper);
return udfpsEnrollView;
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
index 3adfc28b113..5d04cd6c5ed 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
@@ -122,6 +122,16 @@ public class FingerprintEnrollSidecar extends BiometricEnrollSidecar {
public void onEnrollmentError(int errMsgId, CharSequence errString) {
FingerprintEnrollSidecar.super.onEnrollmentError(errMsgId, errString);
}
+
+ @Override
+ public void onPointerDown(int sensorId) {
+ FingerprintEnrollSidecar.super.onPointerDown(sensorId);
+ }
+
+ @Override
+ public void onPointerUp(int sensorId) {
+ FingerprintEnrollSidecar.super.onPointerUp(sensorId);
+ }
};
@Override
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index 36f667daa50..aeedea6af11 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -646,6 +646,7 @@ public class FingerprintSettings extends SubSettings {
if (mAuthenticateSidecar != null) {
mAuthenticateSidecar.setListener(null);
mAuthenticateSidecar.stopAuthentication();
+ mHandler.removeCallbacks(mFingerprintLockoutReset);
}
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java b/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java
index 25689374da8..36325a7b975 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java
@@ -96,6 +96,16 @@ public class FingerprintUpdater {
public void onAcquired(boolean isAcquiredGood) {
mCallback.onAcquired(isAcquiredGood);
}
+
+ @Override
+ public void onPointerDown(int sensorId) {
+ mCallback.onPointerDown(sensorId);
+ }
+
+ @Override
+ public void onPointerUp(int sensorId) {
+ mCallback.onPointerUp(sensorId);
+ }
}
/**
diff --git a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
index f42b8eca2fc..f7f138cbabd 100644
--- a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
+++ b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
@@ -22,19 +22,22 @@ import android.content.Context;
import android.graphics.PointF;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
+import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.util.TypedValue;
import android.view.accessibility.AccessibilityManager;
+import com.android.settings.core.InstrumentedFragment;
+
import java.util.ArrayList;
import java.util.List;
/**
* Helps keep track of enrollment state and animates the progress bar accordingly.
*/
-public class UdfpsEnrollHelper {
+public class UdfpsEnrollHelper extends InstrumentedFragment {
private static final String TAG = "UdfpsEnrollHelper";
private static final String SCALE_OVERRIDE =
@@ -50,6 +53,10 @@ public class UdfpsEnrollHelper {
void onEnrollmentHelp(int remaining, int totalSteps);
void onAcquired(boolean animateIfLastStepGood);
+
+ void onPointerDown(int sensorId);
+
+ void onPointerUp(int sensorId);
}
@NonNull
@@ -124,6 +131,17 @@ public class UdfpsEnrollHelper {
}
}
+ @Override
+ public int getMetricsCategory() {
+ return 0;
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setRetainInstance(true);
+ }
+
void onEnrollmentProgress(int totalSteps, int remaining) {
if (mTotalSteps == -1) {
mTotalSteps = totalSteps;
@@ -144,7 +162,7 @@ public class UdfpsEnrollHelper {
}
void onEnrollmentHelp() {
- if (mListener != null && mTotalSteps != -1) {
+ if (mListener != null) {
mListener.onEnrollmentHelp(mRemainingSteps, mTotalSteps);
}
}
@@ -155,6 +173,18 @@ public class UdfpsEnrollHelper {
}
}
+ void onPointerDown(int sensorId) {
+ if (mListener != null) {
+ mListener.onPointerDown(sensorId);
+ }
+ }
+
+ void onPointerUp(int sensorId) {
+ if (mListener != null) {
+ mListener.onPointerUp(sensorId);
+ }
+ }
+
void setListener(UdfpsEnrollHelper.Listener listener) {
mListener = listener;
diff --git a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollView.java b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollView.java
index 3e3fd0e436d..3d77f0e8b63 100644
--- a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollView.java
+++ b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollView.java
@@ -88,10 +88,22 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
@Override
public void onAcquired(boolean animateIfLastStepGood) {
mHandler.post(() -> {
+ onFingerUp();
if (animateIfLastStepGood) mFingerprintProgressDrawable.onLastStepAcquired();
});
}
+ @Override
+ public void onPointerDown(int sensorId) {
+ onFingerDown();
+ }
+
+
+ @Override
+ public void onPointerUp(int sensorId) {
+ onFingerUp();
+ }
+
void setOverlayParams(UdfpsOverlayParams params) {
mOverlayParams = params;
@@ -99,7 +111,7 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
mProgressBarRadius =
(int) (mOverlayParams.getScaleFactor() * getContext().getResources().getInteger(
R.integer.config_udfpsEnrollProgressBar));
- mSensorRect = mOverlayParams.getSensorBounds();
+ mSensorRect = new Rect(mOverlayParams.getSensorBounds());
onSensorRectUpdated();
});
@@ -123,7 +135,7 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
private void updateDimensions() {
// Original sensorBounds assume portrait mode.
- Rect rotatedBounds = mOverlayParams.getSensorBounds();
+ final Rect rotatedBounds = mOverlayParams.getSensorBounds();
int rotation = mOverlayParams.getRotation();
if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
RotationUtils.rotateBounds(
@@ -137,33 +149,42 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
// Use parent view's and rotatedBound's absolute coordinates to decide the margins of
// UdfpsEnrollView, so that its center keeps consistent with sensor rect's.
ViewGroup parentView = (ViewGroup) getParent();
- int[] coords = parentView.getLocationOnScreen();
- int parentLeft = coords[0];
- int parentTop = coords[1];
- int parentRight = parentLeft + parentView.getWidth();
- int parentBottom = parentTop + parentView.getHeight();
MarginLayoutParams marginLayoutParams = (MarginLayoutParams) getLayoutParams();
FrameLayout.LayoutParams params = (LayoutParams) getLayoutParams();
-
- switch (rotation) {
- case Surface.ROTATION_0:
- case Surface.ROTATION_180:
+ if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
+ parentView.getViewTreeObserver().addOnDrawListener(() -> {
+ final int[] coords = parentView.getLocationOnScreen();
+ final int parentLeft = coords[0];
+ final int parentTop = coords[1];
+ final int parentRight = parentLeft + parentView.getWidth();
params.gravity = Gravity.RIGHT | Gravity.TOP;
- marginLayoutParams.rightMargin = parentRight - rotatedBounds.right - getPaddingX();
- marginLayoutParams.topMargin = rotatedBounds.top - parentTop - getPaddingY();
- break;
- case Surface.ROTATION_90:
+ final int rightMargin = parentRight - rotatedBounds.right - getPaddingX();
+ final int topMargin = rotatedBounds.top - parentTop - getPaddingY();
+ if (marginLayoutParams.rightMargin == rightMargin
+ && marginLayoutParams.topMargin == topMargin) {
+ return;
+ }
+ marginLayoutParams.rightMargin = rightMargin;
+ marginLayoutParams.topMargin = topMargin;
+ setLayoutParams(params);
+ });
+ } else {
+ final int[] coords = parentView.getLocationOnScreen();
+ final int parentLeft = coords[0];
+ final int parentTop = coords[1];
+ final int parentRight = parentLeft + parentView.getWidth();
+ final int parentBottom = parentTop + parentView.getHeight();
+ if (rotation == Surface.ROTATION_90) {
params.gravity = Gravity.RIGHT | Gravity.BOTTOM;
marginLayoutParams.rightMargin = parentRight - rotatedBounds.right - getPaddingX();
marginLayoutParams.bottomMargin =
parentBottom - rotatedBounds.bottom - getPaddingY();
- break;
- case Surface.ROTATION_270:
+ } else if (rotation == Surface.ROTATION_270) {
params.gravity = Gravity.LEFT | Gravity.BOTTOM;
marginLayoutParams.leftMargin = rotatedBounds.left - parentLeft - getPaddingX();
marginLayoutParams.bottomMargin =
parentBottom - rotatedBounds.bottom - getPaddingY();
- break;
+ }
}
params.height = rotatedBounds.height() + 2 * getPaddingX();
diff --git a/src/com/android/settings/display/ScreenResolutionController.java b/src/com/android/settings/display/ScreenResolutionController.java
index a3433d405a5..dca12757e18 100644
--- a/src/com/android/settings/display/ScreenResolutionController.java
+++ b/src/com/android/settings/display/ScreenResolutionController.java
@@ -17,9 +17,7 @@
package com.android.settings.display;
import android.content.Context;
-import android.graphics.Point;
import android.hardware.display.DisplayManager;
-import android.util.Log;
import android.view.Display;
import androidx.annotation.VisibleForTesting;
@@ -27,63 +25,32 @@ import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
/** Controller that switch the screen resolution. */
public class ScreenResolutionController extends BasePreferenceController {
- private static final String TAG = "ScreenResolutionController";
- static final int HIGHRESOLUTION_IDX = 0;
- static final int FULLRESOLUTION_IDX = 1;
+
+ static final int FHD_WIDTH = 1080;
+ static final int QHD_WIDTH = 1440;
private Display mDisplay;
- private Set mSupportedResolutions = null;
- private int mHighWidth = 0;
- private int mFullWidth = 0;
- private int mHighHeight = 0;
- private int mFullHeight = 0;
public ScreenResolutionController(Context context, String key) {
super(context, key);
mDisplay =
mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY);
-
- initSupportedResolutionData();
}
- /**
- * Initialize the resolution data. So far, we support two resolution switching. Save the width
- * and the height for high resolution and full resolution.
- */
- private void initSupportedResolutionData() {
- // Collect and filter the resolutions
- Set resolutions = new HashSet<>();
+ /** Check if the width is supported by the display. */
+ private boolean isSupportedMode(int width) {
for (Display.Mode mode : getSupportedModes()) {
- resolutions.add(new Point(mode.getPhysicalWidth(), mode.getPhysicalHeight()));
+ if (mode.getPhysicalWidth() == width) return true;
}
- mSupportedResolutions = resolutions;
-
- // Get the width and height for high resolution and full resolution
- List resolutionList = new ArrayList<>(resolutions);
- if (resolutionList == null || resolutionList.size() != 2) {
- Log.e(TAG, "No support");
- return;
- }
-
- Collections.sort(resolutionList, (p1, p2) -> p1.x * p1.y - p2.x * p2.y);
- mHighWidth = resolutionList.get(HIGHRESOLUTION_IDX).x;
- mHighHeight = resolutionList.get(HIGHRESOLUTION_IDX).y;
- mFullWidth = resolutionList.get(FULLRESOLUTION_IDX).x;
- mFullHeight = resolutionList.get(FULLRESOLUTION_IDX).y;
+ return false;
}
/** Return true if the device contains two (or more) resolutions. */
protected boolean checkSupportedResolutions() {
- return getHighWidth() != 0 && getFullWidth() != 0;
+ return isSupportedMode(FHD_WIDTH) && isSupportedMode(QHD_WIDTH);
}
@Override
@@ -94,43 +61,20 @@ public class ScreenResolutionController extends BasePreferenceController {
@Override
public CharSequence getSummary() {
String summary = null;
- int width = getDisplayWidth();
- if (width == mHighWidth) {
- summary = mContext.getString(R.string.screen_resolution_option_high);
- } else if (width == mFullWidth) {
- summary = mContext.getString(R.string.screen_resolution_option_full);
- } else {
- summary = mContext.getString(R.string.screen_resolution_title);
+ switch (getDisplayWidth()) {
+ case FHD_WIDTH:
+ summary = mContext.getString(R.string.screen_resolution_summary_high);
+ break;
+ case QHD_WIDTH:
+ summary = mContext.getString(R.string.screen_resolution_summary_highest);
+ break;
+ default:
+ summary = mContext.getString(R.string.screen_resolution_title);
}
return summary;
}
- /** Return all supported resolutions of the device. */
- public Set getAllSupportedResolutions() {
- return this.mSupportedResolutions;
- }
-
- /** Return the high resolution width of the device. */
- public int getHighWidth() {
- return this.mHighWidth;
- }
-
- /** Return the full resolution width of the device. */
- public int getFullWidth() {
- return this.mFullWidth;
- }
-
- /** Return the high resolution height of the device. */
- public int getHighHeight() {
- return this.mHighHeight;
- }
-
- /** Return the full resolution height of the device. */
- public int getFullHeight() {
- return this.mFullHeight;
- }
-
@VisibleForTesting
public int getDisplayWidth() {
return mDisplay.getMode().getPhysicalWidth();
diff --git a/src/com/android/settings/display/ScreenResolutionFragment.java b/src/com/android/settings/display/ScreenResolutionFragment.java
index b16d40b0683..13191cee189 100644
--- a/src/com/android/settings/display/ScreenResolutionFragment.java
+++ b/src/com/android/settings/display/ScreenResolutionFragment.java
@@ -16,6 +16,9 @@
package com.android.settings.display;
+import static com.android.settings.display.ScreenResolutionController.FHD_WIDTH;
+import static com.android.settings.display.ScreenResolutionController.QHD_WIDTH;
+
import android.annotation.Nullable;
import android.app.settings.SettingsEnums;
import android.content.Context;
@@ -45,6 +48,7 @@ import com.android.settingslib.widget.IllustrationPreference;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@@ -55,6 +59,8 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment {
private static final String TAG = "ScreenResolution";
private Resources mResources;
+ private static final int FHD_INDEX = 0;
+ private static final int QHD_INDEX = 1;
private static final String SCREEN_RESOLUTION = "user_selected_resolution";
private Display mDefaultDisplay;
private String[] mScreenResolutionOptions;
@@ -65,9 +71,6 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment {
private DisplayObserver mDisplayObserver;
private AccessibilityManager mAccessibilityManager;
- private int mHighWidth;
- private int mFullWidth;
-
@Override
public void onAttach(Context context) {
super.onAttach(context);
@@ -78,18 +81,11 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment {
mResources = context.getResources();
mScreenResolutionOptions =
mResources.getStringArray(R.array.config_screen_resolution_options_strings);
+ mScreenResolutionSummaries =
+ mResources.getStringArray(R.array.config_screen_resolution_summaries_strings);
+ mResolutions = getAllSupportedResolution();
mImagePreference = new IllustrationPreference(context);
mDisplayObserver = new DisplayObserver(context);
- ScreenResolutionController mController =
- new ScreenResolutionController(context, "fragment");
- mResolutions = mController.getAllSupportedResolutions();
- mHighWidth = mController.getHighWidth();
- mFullWidth = mController.getFullWidth();
- mScreenResolutionSummaries =
- new String[] {
- mHighWidth + " x " + mController.getHighHeight(),
- mFullWidth + " x " + mController.getFullHeight()
- };
}
@Override
@@ -137,6 +133,16 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment {
return candidates;
}
+ /** Get all supported resolutions on the device. */
+ private Set getAllSupportedResolution() {
+ Set resolutions = new HashSet<>();
+ for (Display.Mode mode : mDefaultDisplay.getSupportedModes()) {
+ resolutions.add(new Point(mode.getPhysicalWidth(), mode.getPhysicalHeight()));
+ }
+
+ return resolutions;
+ }
+
/** Get prefer display mode. */
private Display.Mode getPreferMode(int width) {
for (Point resolution : mResolutions) {
@@ -171,7 +177,6 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment {
try {
/** Apply the resolution change. */
- Log.i(TAG, "setUserPreferredDisplayMode: " + mode);
mDefaultDisplay.setUserPreferredDisplayMode(mode);
} catch (Exception e) {
Log.e(TAG, "setUserPreferredDisplayMode() failed", e);
@@ -189,19 +194,16 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment {
/** Get the key corresponding to the resolution. */
@VisibleForTesting
String getKeyForResolution(int width) {
- return width == mHighWidth
- ? mScreenResolutionOptions[ScreenResolutionController.HIGHRESOLUTION_IDX]
- : width == mFullWidth
- ? mScreenResolutionOptions[ScreenResolutionController.FULLRESOLUTION_IDX]
- : null;
+ return width == FHD_WIDTH
+ ? mScreenResolutionOptions[FHD_INDEX]
+ : width == QHD_WIDTH ? mScreenResolutionOptions[QHD_INDEX] : null;
}
/** Get the width corresponding to the resolution key. */
int getWidthForResoluitonKey(String key) {
- return mScreenResolutionOptions[ScreenResolutionController.HIGHRESOLUTION_IDX].equals(key)
- ? mHighWidth
- : mScreenResolutionOptions[ScreenResolutionController.FULLRESOLUTION_IDX].equals(
- key) ? mFullWidth : -1;
+ return mScreenResolutionOptions[FHD_INDEX].equals(key)
+ ? FHD_WIDTH
+ : mScreenResolutionOptions[QHD_INDEX].equals(key) ? QHD_WIDTH : -1;
}
@Override
@@ -246,11 +248,9 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment {
private void updateIllustrationImage(IllustrationPreference preference) {
String key = getDefaultKey();
- if (TextUtils.equals(
- mScreenResolutionOptions[ScreenResolutionController.HIGHRESOLUTION_IDX], key)) {
+ if (TextUtils.equals(mScreenResolutionOptions[FHD_INDEX], key)) {
preference.setLottieAnimationResId(R.drawable.screen_resolution_1080p);
- } else if (TextUtils.equals(
- mScreenResolutionOptions[ScreenResolutionController.FULLRESOLUTION_IDX], key)) {
+ } else if (TextUtils.equals(mScreenResolutionOptions[QHD_INDEX], key)) {
preference.setLottieAnimationResId(R.drawable.screen_resolution_1440p);
}
}
@@ -408,8 +408,6 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment {
return false;
}
- Log.i(TAG,
- "resolution changed from " + mPreviousWidth.get() + " to " + getCurrentWidth());
return true;
}
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
index 9551404e2d2..d53afdf5b98 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
@@ -487,7 +487,7 @@ public class BatteryDiffEntry {
@Override
public Drawable getAppIcon() {
- return mContext.getDrawable(R.drawable.ic_settings_ethernet);
+ return mContext.getDrawable(R.drawable.ic_settings_battery_usage_others);
}
@Override
diff --git a/src/com/android/settings/localepicker/AppLocalePickerActivity.java b/src/com/android/settings/localepicker/AppLocalePickerActivity.java
index 2629b6ca639..aecc5710252 100644
--- a/src/com/android/settings/localepicker/AppLocalePickerActivity.java
+++ b/src/com/android/settings/localepicker/AppLocalePickerActivity.java
@@ -78,6 +78,7 @@ public class AppLocalePickerActivity extends SettingsBaseActivity
mContextAsUser,
this,
false /* translate only */,
+ null,
mPackageName,
this);
mAppLocaleDetails = AppLocaleDetails.newInstance(mPackageName, mContextAsUser.getUserId());
diff --git a/src/com/android/settings/localepicker/LocaleListEditor.java b/src/com/android/settings/localepicker/LocaleListEditor.java
index 75ea768e232..8fcfefc3131 100644
--- a/src/com/android/settings/localepicker/LocaleListEditor.java
+++ b/src/com/android/settings/localepicker/LocaleListEditor.java
@@ -318,6 +318,7 @@ public class LocaleListEditor extends RestrictedSettingsFragment {
final Intent intent = new Intent(getActivity(),
LocalePickerWithRegionActivity.class);
+ intent.putExtras(getActivity().getIntent().getExtras());
startActivityForResult(intent, REQUEST_LOCALE_PICKER);
}
});
diff --git a/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java b/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java
index a8c93c17944..9c7e6370db3 100644
--- a/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java
+++ b/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java
@@ -19,6 +19,9 @@ package com.android.settings.localepicker;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
+import android.os.LocaleList;
+import android.provider.Settings;
+import android.util.Log;
import android.view.MenuItem;
import com.android.internal.app.LocalePickerWithRegion;
@@ -29,7 +32,7 @@ import com.android.settings.core.SettingsBaseActivity;
/** A activity to show the locale picker page. */
public class LocalePickerWithRegionActivity extends SettingsBaseActivity
implements LocalePickerWithRegion.LocaleSelectedListener {
-
+ private static final String TAG = LocalePickerWithRegionActivity.class.getSimpleName();
private static final String PARENT_FRAGMENT_NAME = "localeListEditor";
@Override
@@ -37,9 +40,20 @@ public class LocalePickerWithRegionActivity extends SettingsBaseActivity
super.onCreate(savedInstanceState);
getActionBar().setDisplayHomeAsUpEnabled(true);
setTitle(R.string.add_a_language);
+ LocaleList explicitLocales = null;
+ if (isDeviceDemoMode()) {
+ Bundle bundle = getIntent().getExtras();
+ explicitLocales = bundle == null
+ ? null
+ : bundle.getParcelable(Settings.EXTRA_EXPLICIT_LOCALES, LocaleList.class);
+ Log.i(TAG, "Has explicit locales : " + explicitLocales);
+ }
final LocalePickerWithRegion selector = LocalePickerWithRegion.createLanguagePicker(
- this, LocalePickerWithRegionActivity.this, false /* translate only */);
+ this,
+ LocalePickerWithRegionActivity.this,
+ false /* translate only */,
+ explicitLocales);
getFragmentManager()
.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
@@ -78,5 +92,10 @@ public class LocalePickerWithRegionActivity extends SettingsBaseActivity
finish();
}
}
+
+ private boolean isDeviceDemoMode() {
+ return Settings.Global.getInt(
+ getContentResolver(), Settings.Global.DEVICE_DEMO_MODE, 0) == 1;
+ }
}
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/specialaccess/PictureInPictureTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/specialaccess/PictureInPictureTest.kt
new file mode 100644
index 00000000000..5e2b8c6e4cd
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/spa/app/specialaccess/PictureInPictureTest.kt
@@ -0,0 +1,178 @@
+/*
+ * 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.specialaccess
+
+import android.app.AppOpsManager
+import android.content.Context
+import android.content.pm.ActivityInfo
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.PackageInfoFlags
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.android.settingslib.spaprivileged.model.app.AppOpsController
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.runTest
+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.Spy
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.Mockito.`when` as whenever
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
+class PictureInPictureTest {
+ @get:Rule
+ val mockito: MockitoRule = MockitoJUnit.rule()
+
+ @Spy
+ private val context: Context = ApplicationProvider.getApplicationContext()
+
+ @Mock
+ private lateinit var packageManager: PackageManager
+
+ private lateinit var listModel: PictureInPictureListModel
+
+ @Before
+ fun setUp() {
+ whenever(context.packageManager).thenReturn(packageManager)
+ whenever(packageManager.getInstalledPackagesAsUser(any(), anyInt()))
+ .thenReturn(emptyList())
+ listModel = PictureInPictureListModel(context)
+ }
+
+ @Test
+ fun pageTitleResId() {
+ assertThat(listModel.pageTitleResId).isEqualTo(R.string.picture_in_picture_title)
+ }
+
+ @Test
+ fun switchTitleResId() {
+ assertThat(listModel.switchTitleResId)
+ .isEqualTo(R.string.picture_in_picture_app_detail_switch)
+ }
+
+ @Test
+ fun footerResId() {
+ assertThat(listModel.footerResId).isEqualTo(R.string.picture_in_picture_app_detail_summary)
+ }
+
+ @Test
+ fun transform() = runTest {
+ whenever(packageManager.getInstalledPackagesAsUser(any(), anyInt()))
+ .thenReturn(listOf(PICTURE_IN_PICTURE_PACKAGE_INFO))
+
+ val recordListFlow = listModel.transform(
+ userIdFlow = flowOf(USER_ID),
+ appListFlow = flowOf(listOf(PICTURE_IN_PICTURE_APP)),
+ )
+
+ val recordList = recordListFlow.first()
+ assertThat(recordList).hasSize(1)
+ val record = recordList[0]
+ assertThat(record.app).isSameInstanceAs(PICTURE_IN_PICTURE_APP)
+ assertThat(record.isSupport).isTrue()
+ }
+
+ @Test
+ fun transformItem() {
+ whenever(
+ packageManager.getPackageInfoAsUser(
+ eq(PICTURE_IN_PICTURE_PACKAGE_NAME), any(), eq(USER_ID)
+ )
+ ).thenReturn(PICTURE_IN_PICTURE_PACKAGE_INFO)
+
+ val record = listModel.transformItem(PICTURE_IN_PICTURE_APP)
+
+ assertThat(record.app).isSameInstanceAs(PICTURE_IN_PICTURE_APP)
+ assertThat(record.isSupport).isTrue()
+ }
+
+ @Test
+ fun filter_isSupport() = runTest {
+ val record = createRecord(isSupport = true)
+
+ val recordListFlow = listModel.filter(flowOf(USER_ID), flowOf(listOf(record)))
+
+ val recordList = recordListFlow.first()
+ assertThat(recordList).hasSize(1)
+ }
+
+ @Test
+ fun filter_notSupport() = runTest {
+ val record = createRecord(isSupport = false)
+
+ val recordListFlow = listModel.filter(flowOf(USER_ID), flowOf(listOf(record)))
+
+ val recordList = recordListFlow.first()
+ assertThat(recordList).isEmpty()
+ }
+
+ @Test
+ fun isChangeable_isSupport() {
+ val record = createRecord(isSupport = true)
+
+ val isChangeable = listModel.isChangeable(record)
+
+ assertThat(isChangeable).isTrue()
+ }
+
+ @Test
+ fun isChangeable_notSupport() {
+ val record = createRecord(isSupport = false)
+
+ val isChangeable = listModel.isChangeable(record)
+
+ assertThat(isChangeable).isFalse()
+ }
+
+ private fun createRecord(isSupport: Boolean) = PictureInPictureRecord(
+ app = PICTURE_IN_PICTURE_APP,
+ isSupport = isSupport,
+ appOpsController = AppOpsController(
+ context = context,
+ app = PICTURE_IN_PICTURE_APP,
+ op = AppOpsManager.OP_PICTURE_IN_PICTURE,
+ ),
+ )
+
+ private companion object {
+ const val USER_ID = 0
+ const val PICTURE_IN_PICTURE_PACKAGE_NAME = "picture.in.picture.package.name"
+ val PICTURE_IN_PICTURE_APP = ApplicationInfo().apply {
+ packageName = PICTURE_IN_PICTURE_PACKAGE_NAME
+ }
+ val PICTURE_IN_PICTURE_PACKAGE_INFO = PackageInfo().apply {
+ packageName = PICTURE_IN_PICTURE_PACKAGE_NAME
+ activities = arrayOf(ActivityInfo().apply {
+ flags = ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE
+ })
+ }
+ }
+}
\ No newline at end of file