From f70e351d1a3bc7765da1fa8f9e0bb52d425b27e4 Mon Sep 17 00:00:00 2001 From: Oli Lan Date: Fri, 26 Aug 2022 18:29:16 +0100 Subject: [PATCH 1/5] Prevent exfiltration of system files via avatar picker. This adds mitigations to prevent system files being exfiltrated via the settings content provider when a content URI is provided as a chosen user image. The mitigations are: 1) Copy the image to a new URI rather than the existing takePictureUri prior to cropping. 2) Only allow a system handler to respond to the CROP intent. This is a fixed version of ag/17003629, to address b/239513606. Bug: 187702830 Test: build and check functionality Merged-In: I15e15ad88b768a5b679de32c5429d921d850a3cb Change-Id: I98eea867f926c508456ec9bc654e24eeeffa0e54 --- .../users/EditUserPhotoController.java | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/com/android/settings/users/EditUserPhotoController.java b/src/com/android/settings/users/EditUserPhotoController.java index f62a2d5970f..f1831f7120b 100644 --- a/src/com/android/settings/users/EditUserPhotoController.java +++ b/src/com/android/settings/users/EditUserPhotoController.java @@ -21,7 +21,9 @@ import android.content.ClipData; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; @@ -77,6 +79,7 @@ public class EditUserPhotoController { private static final int REQUEST_CODE_TAKE_PHOTO = 1002; private static final int REQUEST_CODE_CROP_PHOTO = 1003; + private static final String PRE_CROP_PICTURE_FILE_NAME = "PreCropEditUserPhoto.jpg"; private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg"; private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg"; private static final String NEW_USER_PHOTO_FILE_NAME = "NewUserPhoto.png"; @@ -87,6 +90,7 @@ public class EditUserPhotoController { private final Fragment mFragment; private final ImageView mImageView; + private final Uri mPreCropPictureUri; private final Uri mCropPictureUri; private final Uri mTakePictureUri; @@ -98,6 +102,8 @@ public class EditUserPhotoController { mContext = view.getContext(); mFragment = fragment; mImageView = view; + + mPreCropPictureUri = createTempImageUri(mContext, PRE_CROP_PICTURE_FILE_NAME, !waiting); mCropPictureUri = createTempImageUri(mContext, CROP_PICTURE_FILE_NAME, !waiting); mTakePictureUri = createTempImageUri(mContext, TAKE_PICTURE_FILE_NAME, !waiting); mPhotoSize = getPhotoSize(mContext); @@ -132,7 +138,7 @@ public class EditUserPhotoController { case REQUEST_CODE_TAKE_PHOTO: case REQUEST_CODE_CHOOSE_PHOTO: if (mTakePictureUri.equals(pictureUri)) { - cropPhoto(); + cropPhoto(pictureUri); } else { copyAndCropPhoto(pictureUri); } @@ -241,7 +247,7 @@ public class EditUserPhotoController { protected Void doInBackground(Void... params) { final ContentResolver cr = mContext.getContentResolver(); try (InputStream in = cr.openInputStream(pictureUri); - OutputStream out = cr.openOutputStream(mTakePictureUri)) { + OutputStream out = cr.openOutputStream(mPreCropPictureUri)) { Streams.copy(in, out); } catch (IOException e) { Log.w(TAG, "Failed to copy photo", e); @@ -252,27 +258,38 @@ public class EditUserPhotoController { @Override protected void onPostExecute(Void result) { if (!mFragment.isAdded()) return; - cropPhoto(); + cropPhoto(mPreCropPictureUri); } }.execute(); } - private void cropPhoto() { + private void cropPhoto(final Uri pictureUri) { // TODO: Use a public intent, when there is one. Intent intent = new Intent("com.android.camera.action.CROP"); - intent.setDataAndType(mTakePictureUri, "image/*"); + intent.setDataAndType(pictureUri, "image/*"); appendOutputExtra(intent, mCropPictureUri); appendCropExtras(intent); - if (intent.resolveActivity(mContext.getPackageManager()) != null) { - try { - StrictMode.disableDeathOnFileUriExposure(); - mFragment.startActivityForResult(intent, REQUEST_CODE_CROP_PHOTO); - } finally { - StrictMode.enableDeathOnFileUriExposure(); + try { + StrictMode.disableDeathOnFileUriExposure(); + if (startSystemActivityForResult(intent, REQUEST_CODE_CROP_PHOTO)) { + return; } - } else { - onPhotoCropped(mTakePictureUri, false); + } finally { + StrictMode.enableDeathOnFileUriExposure(); } + onPhotoCropped(mTakePictureUri, false); + } + + private boolean startSystemActivityForResult(Intent intent, int code) { + List resolveInfos = mContext.getPackageManager() + .queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY); + if (resolveInfos.isEmpty()) { + Log.w(TAG, "No system package activity could be found for code " + code); + return false; + } + intent.setPackage(resolveInfos.get(0).activityInfo.packageName); + mFragment.startActivityForResult(intent, code); + return true; } private void appendOutputExtra(Intent intent, Uri pictureUri) { From 82a42834b1635a77fe9f0e5127cf5df5d0b5455d Mon Sep 17 00:00:00 2001 From: lbill Date: Wed, 7 Sep 2022 03:14:14 +0000 Subject: [PATCH 2/5] Fix regression of pressing power key cancel sfps enrollment Previous ag/19699461 used to fix UdfpsControllerOverlay bug. However, we didn't consider a feature click power button to notify user with a Toast on sfps project. Bug: 245383975 Bug: 228261883 Bug: 242478941 Bug: 227905887 Test: make RunSettingsRoboTests ROBOTEST_FILTER=FingerprintEnrollEnrollingTest Test: manual verify sfps enrollment, press/long press power key would not cancel enrollment. Test: manual verify udfps enrollment, UdfpsControllerOverlay lose focus cancel enrollment. Change-Id: I44394bdb91660b27a704064a7f7cdc5d0ad95d30 --- .../fingerprint/FingerprintEnrollEnrolling.java | 4 +++- .../fingerprint/FingerprintEnrollEnrollingTest.java | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java index b1b18ff1f56..64a08d3c996 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java @@ -203,7 +203,9 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { // Do NOT cancel enrollment progress after rotating, adding mIsOrientationChanged // to judge if the focus changed was triggered by rotation, current WMS has triple callbacks // (true > false > true), we need to reset mIsOrientationChanged when !hasFocus callback. - if (!mIsOrientationChanged) { + // Side fps do not have to synchronize udfpsController overlay state, we should bypass sfps + // from onWindowFocusChanged() as long press sfps power key will prompt dialog to users. + if (!mIsOrientationChanged && !mCanAssumeSfps) { onCancelEnrollment(FINGERPRINT_ERROR_USER_CANCELED); } else { mIsOrientationChanged = false; diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java index ef31c392af7..2c864d6d92b 100644 --- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java +++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java @@ -222,6 +222,16 @@ public class FingerprintEnrollEnrollingTest { ); } + @Test + public void fingerprintSfpsEnrollment_loseFocus_shouldNotCancel() { + initializeActivityFor(FingerprintSensorProperties.TYPE_POWER_BUTTON); + + mActivity.onEnrollmentProgressChange(1, 1); + mActivity.onWindowFocusChanged(true); + + verify(mActivity, never()).onCancelEnrollment(anyInt()); + } + private void initializeActivityFor(int sensorType) { final List componentInfo = new ArrayList<>(); final FingerprintSensorPropertiesInternal prop = From 70a63abfe4d2e1cdc05c4cd02529e0548f29cc7f Mon Sep 17 00:00:00 2001 From: menghanli Date: Thu, 4 Aug 2022 11:50:06 +0800 Subject: [PATCH 3/5] Fix insufficient contrast for the strings "Dimmer" and "Brighter" in the light theme Apply same the sub text style from seekbar preference Bug: 219752953 Bug: 229722937 Bug: 245093240 Fix: 245093240 Test: Manual testing Change-Id: If107452b942e23dee17c73873f4aedc3a25c7f5d (cherry picked from commit a8b9c805a2f46bdfedb0c45d6ec5bc660c5d8172) --- res/layout/preference_labeled_slider.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/layout/preference_labeled_slider.xml b/res/layout/preference_labeled_slider.xml index a11d574b319..ae7027defe8 100644 --- a/res/layout/preference_labeled_slider.xml +++ b/res/layout/preference_labeled_slider.xml @@ -69,6 +69,8 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="start|top" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:attr/textColorSecondary" android:gravity="start" android:layout_weight="1"/> @@ -77,6 +79,8 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="end|top" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:attr/textColorSecondary" android:gravity="end" android:layout_weight="1"/> From aaee157fddea04eec3ada38744197a8f1d45c7a6 Mon Sep 17 00:00:00 2001 From: menghanli Date: Thu, 7 Jul 2022 09:00:09 +0800 Subject: [PATCH 4/5] Fix extra dim turns on failed in setting search bar Root cause: Don't call displayPreference before setChecked called. Solution: Don't show quick settings tooltips if preference is not ready. Bug: 237850687 Bug: 244676175 Test: make RunSettingsRoboTests ROBOTEST_FILTER=AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest Change-Id: I52425190cce4ab3cf31be025a743bf8b212fa1f9 Merged-In: I52425190cce4ab3cf31be025a743bf8b212fa1f9 --- ...kSettingsPrimarySwitchPreferenceController.java | 5 +++++ ...tingsPrimarySwitchPreferenceControllerTest.java | 14 +++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java index d272a0be49f..429fd9deca9 100644 --- a/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java +++ b/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java @@ -102,6 +102,11 @@ public abstract class AccessibilityQuickSettingsPrimarySwitchPreferenceControlle } private void showQuickSettingsTooltipIfNeeded() { + if (mPreference == null) { + // Returns if no preference found by slice highlight menu. + return; + } + final ComponentName tileComponentName = getTileComponentName(); if (tileComponentName == null) { // Returns if no tile service assigned. diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest.java index 89c91209ffd..deab7453337 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest.java @@ -118,18 +118,29 @@ public class AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest { mController = new TestAccessibilityQuickSettingsPrimarySwitchPreferenceController(mContext, TEST_KEY); when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); - mController.displayPreference(mScreen); } @Test public void setChecked_showTooltipView() { + mController.displayPreference(mScreen); + mController.setChecked(true); assertThat(getLatestPopupWindow().isShowing()).isTrue(); } + @Test + public void setChecked_notCallDisplayPreference_notShowTooltipView() { + // Simulates the slice highlight menu that does not call {@link #displayPreference} before + // {@link #setChecked} called. + mController.setChecked(true); + + assertThat(getLatestPopupWindow()).isNull(); + } + @Test public void setChecked_tooltipViewShown_notShowTooltipView() { + mController.displayPreference(mScreen); mController.setChecked(true); getLatestPopupWindow().dismiss(); mController.setChecked(false); @@ -142,6 +153,7 @@ public class AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest { @Test @Config(shadows = ShadowFragment.class) public void restoreValueFromSavedInstanceState_showTooltipView() { + mController.displayPreference(mScreen); mController.setChecked(true); final Bundle savedInstanceState = new Bundle(); savedInstanceState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true); From e10799c774e04a4ca19017fe087bf4a3789d4915 Mon Sep 17 00:00:00 2001 From: Peter_Liang Date: Wed, 1 Jun 2022 16:12:19 +0800 Subject: [PATCH 5/5] Fix the preview section incorrectly ordered of the display size and text. Goals: Set correct order into. Fix: 233326281 Test: manual test Change-Id: I88c65aa9c3f05281a5c5090c2ca9503327bb580f Merged-In: I88c65aa9c3f05281a5c5090c2ca9503327bb580f (cherry picked from commit 4b136204570bd61ccd6ba2277c6204b4defa8df9) --- .../settings/accessibility/TextReadingPreviewController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/android/settings/accessibility/TextReadingPreviewController.java b/src/com/android/settings/accessibility/TextReadingPreviewController.java index 1be8c70f4f6..98767d9d0ca 100644 --- a/src/com/android/settings/accessibility/TextReadingPreviewController.java +++ b/src/com/android/settings/accessibility/TextReadingPreviewController.java @@ -108,6 +108,7 @@ class TextReadingPreviewController extends BasePreferenceController implements final PreviewPagerAdapter pagerAdapter = new PreviewPagerAdapter(mContext, isLayoutRtl, PREVIEW_SAMPLE_RES_IDS, createConfig(origConfig)); mPreviewPreference.setPreviewAdapter(pagerAdapter); + mPreviewPreference.setCurrentItem(isLayoutRtl ? PREVIEW_SAMPLE_RES_IDS.length - 1 : 0); pagerAdapter.setPreviewLayer(/* newLayerIndex= */ 0, /* currentLayerIndex= */ 0, /* currentFrameIndex= */ 0, /* animate= */ false);