diff options
36 files changed, 463 insertions, 88 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 6fd17157ee86..e3e90f506663 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -51985,6 +51985,7 @@ package android.view.inputmethod { method public int getSubtypeCount(); method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager); method public CharSequence loadLabel(android.content.pm.PackageManager); + method public boolean shouldShowInInputMethodPicker(); method public boolean suppressesSpellChecker(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InputMethodInfo> CREATOR; diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index 6e99b0debc36..dfd935d0dfb3 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -67,3 +67,6 @@ per-file *Zygote* = file:/ZYGOTE_OWNERS # RecoverySystem per-file *Recovery* = file:/services/core/java/com/android/server/recoverysystem/OWNERS + +# Bugreporting +per-file Bugreport* = file:/platform/frameworks/native:/cmds/dumpstate/OWNERS diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index c26b302db983..9b463bb9538f 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -638,10 +638,11 @@ public final class InputMethodInfo implements Parcelable { } /** - * Return {@code true} if this input method should be shown in the IME picker. - * @hide + * Returns {@code true} if this input method should be shown in menus for selecting an Input + * Method, such as the system Input Method Picker. This is {@code false} if the IME is intended + * to be accessed programmatically. */ - public boolean showInInputMethodPicker() { + public boolean shouldShowInInputMethodPicker() { return mShowInInputMethodPicker; } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 50fb01b49616..f1fa2bcddd38 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -5772,6 +5772,16 @@ android:protectionLevel="normal" /> <uses-permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION"/> + <!-- Allows an application to take screenshots of layers that normally would be blacked out when + a screenshot is taken. Specifically, layers that have the flag + {@link android.view.SurfaceControl#SECURE} will be screenshot if the caller requests to + capture secure layers. Normally those layers will be rendered black. + <p>Not for use by third-party applications. + @hide + --> + <permission android:name="android.permission.CAPTURE_BLACKOUT_CONTENT" + android:protectionLevel="signature" /> + <!-- Attribution for Geofencing service. --> <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/> <!-- Attribution for Country Detector. --> diff --git a/core/res/res/drawable/work_widget_mask_view_background.xml b/core/res/res/drawable/work_widget_mask_view_background.xml new file mode 100644 index 000000000000..ce9c514695c4 --- /dev/null +++ b/core/res/res/drawable/work_widget_mask_view_background.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2021 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. +--> +<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> + <solid android:color="?android:attr/colorSurfaceVariant" /> + <corners android:radius="@dimen/system_app_widget_background_radius" /> +</shape> diff --git a/core/res/res/layout/work_widget_mask_view.xml b/core/res/res/layout/work_widget_mask_view.xml index e7174cc58438..86c5d13ede40 100644 --- a/core/res/res/layout/work_widget_mask_view.xml +++ b/core/res/res/layout/work_widget_mask_view.xml @@ -18,14 +18,14 @@ Copyright (C) 2015 The Android Open Source Project android:id="@+id/work_widget_mask_frame" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="?android:attr/colorSurfaceVariant" + android:background="@drawable/work_widget_mask_view_background" android:importantForAccessibility="noHideDescendants" android:clickable="true"> <com.android.internal.widget.DisableImageView android:id="@+id/work_widget_app_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_width="48dp" + android:layout_height="48dp" android:layout_gravity="center" android:clickable="false" /> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index aa0d23bf3385..3edc17be3592 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4796,8 +4796,9 @@ <!-- Whether to select voice/data/sms preference without user confirmation --> <bool name="config_voice_data_sms_auto_fallback">false</bool> - <!-- Whether to enable the one-handed keyguard on the lock screen for wide-screen devices. --> - <bool name="config_enableOneHandedKeyguard">false</bool> + <!-- Whether to enable dynamic keyguard positioning for wide screen devices (e.g. only using + half of the screen, to be accessible using only one hand). --> + <bool name="config_enableDynamicKeyguardPositioning">false</bool> <!-- Whether to allow the caching of the SIM PIN for verification after unattended reboot --> <bool name="config_allow_pin_storage_for_unattended_reboot">true</bool> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index d440173ef199..ce558fb63bb8 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4259,7 +4259,7 @@ <java-symbol type="bool" name="config_voice_data_sms_auto_fallback" /> - <java-symbol type="bool" name="config_enableOneHandedKeyguard" /> + <java-symbol type="bool" name="config_enableDynamicKeyguardPositioning" /> <java-symbol type="attr" name="colorAccentPrimary" /> <java-symbol type="attr" name="colorAccentSecondary" /> diff --git a/libs/WindowManager/Shell/AndroidManifest.xml b/libs/WindowManager/Shell/AndroidManifest.xml index 6bd0e0a4ff86..10df726a8c90 100644 --- a/libs/WindowManager/Shell/AndroidManifest.xml +++ b/libs/WindowManager/Shell/AndroidManifest.xml @@ -18,6 +18,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.wm.shell"> <!-- System permission required by WM Shell Task Organizer. --> + <uses-permission android:name="android.permission.CAPTURE_BLACKOUT_CONTENT" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> <uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" /> <uses-permission android:name="android.permission.READ_FRAME_BUFFER" /> diff --git a/packages/SystemUI/res/color/media_player_solid_button_bg.xml b/packages/SystemUI/res/color/media_player_solid_button_bg.xml new file mode 100644 index 000000000000..96685ab58303 --- /dev/null +++ b/packages/SystemUI/res/color/media_player_solid_button_bg.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 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. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> + <item android:color="?androidprv:attr/colorAccentTertiary"/> +</selector>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml index 9e67258f68da..8c54e2c1cec4 100644 --- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml +++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml @@ -75,7 +75,7 @@ android:id="@+id/media_logo1" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - style="@style/MediaPlayer.AppIcon.Recommendation" /> + style="@style/MediaPlayer.AppIcon" /> <ImageView android:id="@+id/media_cover2" @@ -91,7 +91,7 @@ android:id="@+id/media_logo2" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - style="@style/MediaPlayer.AppIcon.Recommendation" /> + style="@style/MediaPlayer.AppIcon" /> <ImageView android:id="@+id/media_cover3" @@ -107,7 +107,7 @@ android:id="@+id/media_logo3" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - style="@style/MediaPlayer.AppIcon.Recommendation" /> + style="@style/MediaPlayer.AppIcon" /> <ImageView android:id="@+id/media_cover4" @@ -123,7 +123,7 @@ android:id="@+id/media_logo4" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - style="@style/MediaPlayer.AppIcon.Recommendation" /> + style="@style/MediaPlayer.AppIcon" /> <ImageView android:id="@+id/media_cover5" @@ -139,7 +139,7 @@ android:id="@+id/media_logo5" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - style="@style/MediaPlayer.AppIcon.Recommendation" /> + style="@style/MediaPlayer.AppIcon" /> <ImageView android:id="@+id/media_cover6" @@ -155,7 +155,7 @@ android:id="@+id/media_logo6" android:layout_width="@dimen/qs_media_icon_size" android:layout_height="@dimen/qs_media_icon_size" - style="@style/MediaPlayer.AppIcon.Recommendation" /> + style="@style/MediaPlayer.AppIcon" /> <!-- Long press menu --> <TextView diff --git a/packages/SystemUI/res/layout/media_view.xml b/packages/SystemUI/res/layout/media_view.xml index 8dbbd4a4a66f..e999872ac805 100644 --- a/packages/SystemUI/res/layout/media_view.xml +++ b/packages/SystemUI/res/layout/media_view.xml @@ -145,6 +145,7 @@ android:layout_width="@dimen/qs_seamless_icon_size" android:layout_height="@dimen/qs_seamless_icon_size" android:layout_gravity="center" + android:tint="?android:attr/textColorPrimary" android:src="@*android:drawable/ic_media_seamless" /> <TextView android:id="@+id/media_seamless_text" diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index df68dbdec9c8..06ba03d40dd9 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -649,19 +649,14 @@ </style> <style name="MediaPlayer.SolidButton"> - <item name="android:backgroundTint">?android:attr/colorAccent</item> + <item name="android:backgroundTint">@color/media_player_solid_button_bg</item> <item name="android:tint">?android:attr/colorPrimary</item> - <item name="android:textColor">?android:attr/colorPrimary</item> + <item name="android:textColor">?android:attr/textColorPrimary</item> </style> <style name="MediaPlayer.AppIcon"> <item name="android:background">@drawable/qs_media_icon_background</item> - <item name="android:backgroundTint">?android:attr/colorPrimary</item> - <item name="android:tint">?android:attr/colorAccent</item> - </style> - - <style name="MediaPlayer.AppIcon.Recommendation" parent="MediaPlayer.AppIcon"> - <item name="android:tint">@color/transparent</item> + <item name="android:backgroundTint">?android:attr/textColorPrimary</item> </style> <style name="MediaPlayer.Album"> diff --git a/packages/SystemUI/res/xml/media_collapsed.xml b/packages/SystemUI/res/xml/media_collapsed.xml index bdb8c049b861..a03a1d3accfb 100644 --- a/packages/SystemUI/res/xml/media_collapsed.xml +++ b/packages/SystemUI/res/xml/media_collapsed.xml @@ -69,6 +69,7 @@ android:layout_marginBottom="@dimen/qs_media_padding" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" + app:layout_constraintBottom_toBottomOf="parent" /> <!-- Song name --> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java index d06c8bc6bffe..3ebd652b3467 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java @@ -481,7 +481,7 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView> if (resources.getBoolean(R.bool.can_use_one_handed_bouncer) && resources.getBoolean( - com.android.internal.R.bool.config_enableOneHandedKeyguard)) { + com.android.internal.R.bool.config_enableDynamicKeyguardPositioning)) { gravity = resources.getInteger( R.integer.keyguard_host_view_one_handed_gravity); } else { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 54ecf955ed11..ca4d73b6de5d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -278,7 +278,7 @@ public class KeyguardSecurityContainer extends FrameLayout { private boolean canUseOneHandedBouncer() { // Is it enabled? if (!getResources().getBoolean( - com.android.internal.R.bool.config_enableOneHandedKeyguard)) { + com.android.internal.R.bool.config_enableDynamicKeyguardPositioning)) { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index c608dc78e583..e213dfe3bdd3 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -45,6 +45,7 @@ import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.constraintlayout.widget.ConstraintSet; +import com.android.settingslib.Utils; import com.android.settingslib.widget.AdaptiveIcon; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; @@ -303,11 +304,23 @@ public class MediaControlPanel { } // App icon - ImageView appIcon = mPlayerViewHolder.getAppIcon(); - if (data.getAppIcon() != null) { - appIcon.setImageIcon(data.getAppIcon()); + ImageView appIconView = mPlayerViewHolder.getAppIcon(); + appIconView.clearColorFilter(); + if (data.getAppIcon() != null && !data.getResumption()) { + appIconView.setImageIcon(data.getAppIcon()); + int color = Utils.getColorAttrDefaultColor(mContext, + com.android.internal.R.attr.colorAccentTertiary); + appIconView.setColorFilter(color); } else { - appIcon.setImageResource(R.drawable.ic_music_note); + appIconView.setColorFilter(getGrayscaleFilter()); + try { + Drawable icon = mContext.getPackageManager().getApplicationIcon( + data.getPackageName()); + appIconView.setImageDrawable(icon); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, "Cannot find icon for package " + data.getPackageName(), e); + appIconView.setImageResource(R.drawable.ic_music_note); + } } // Song name @@ -400,7 +413,7 @@ public class MediaControlPanel { setVisibleAndAlpha(collapsedSet, ACTION_IDS[i], false /*visible */); setVisibleAndAlpha(expandedSet, ACTION_IDS[i], false /* visible */); } - // If no expanded buttons, set the first view as INVISIBLE so z remains constant + // If no actions, set the first view as INVISIBLE so expanded height remains constant if (actionIcons.size() == 0) { expandedSet.setVisibility(ACTION_IDS[0], ConstraintSet.INVISIBLE); } @@ -514,9 +527,9 @@ public class MediaControlPanel { // Get the logo from app's package name when applicable. String packageName = extras.getString(EXTRAS_MEDIA_SOURCE_PACKAGE_NAME); try { - Drawable drawable = mContext.getPackageManager().getApplicationIcon( + icon = mContext.getPackageManager().getApplicationIcon( packageName); - icon = convertToGrayscale(drawable); + icon.setColorFilter(getGrayscaleFilter()); } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "No media source icon can be fetched via package name", e); } @@ -646,13 +659,10 @@ public class MediaControlPanel { return (state.getState() == PlaybackState.STATE_PLAYING); } - /** Convert the pass-in source drawable to a grayscale one. */ - private Drawable convertToGrayscale(Drawable drawable) { + private ColorMatrixColorFilter getGrayscaleFilter() { ColorMatrix matrix = new ColorMatrix(); matrix.setSaturation(0); - ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix); - drawable.setColorFilter(filter); - return drawable; + return new ColorMatrixColorFilter(matrix); } private void setVisibleAndAlpha(ConstraintSet set, int actionId, boolean visible) { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java index c6373f5e0c5f..bcef43c93be4 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java @@ -24,6 +24,7 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -41,6 +42,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.media.MediaDevice; +import com.android.settingslib.utils.ThreadUtils; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; @@ -116,6 +118,7 @@ public abstract class MediaOutputBaseAdapter extends final View mDivider; final View mBottomDivider; final CheckBox mCheckBox; + private String mDeviceId; MediaDeviceBaseViewHolder(View view) { super(view); @@ -134,8 +137,17 @@ public abstract class MediaOutputBaseAdapter extends } void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin) { - mTitleIcon.setImageIcon(mController.getDeviceIconCompat(device).toIcon(mContext)); - setMargin(topMargin, bottomMargin); + mDeviceId = device.getId(); + ThreadUtils.postOnBackgroundThread(() -> { + Icon icon = mController.getDeviceIconCompat(device).toIcon(mContext); + ThreadUtils.postOnMainThread(() -> { + if (!TextUtils.equals(mDeviceId, device.getId())) { + return; + } + mTitleIcon.setImageIcon(icon); + setMargin(topMargin, bottomMargin); + }); + }); } void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java index 42314bf3643f..6f2c56515767 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java @@ -81,7 +81,7 @@ public class KeyguardHostViewControllerTest extends SysuiTestCase { mTestableResources.addOverride( R.bool.can_use_one_handed_bouncer, false); mTestableResources.addOverride( - com.android.internal.R.bool.config_enableOneHandedKeyguard, false); + com.android.internal.R.bool.config_enableDynamicKeyguardPositioning, false); when(mKeyguardSecurityContainerControllerFactory.create(any( KeyguardSecurityContainer.SecurityCallback.class))) @@ -150,7 +150,7 @@ public class KeyguardHostViewControllerTest extends SysuiTestCase { mTestableResources.addOverride( R.bool.can_use_one_handed_bouncer, false); mTestableResources.addOverride( - com.android.internal.R.bool.config_enableOneHandedKeyguard, false); + com.android.internal.R.bool.config_enableDynamicKeyguardPositioning, false); mKeyguardHostViewController.init(); assertEquals( @@ -161,7 +161,7 @@ public class KeyguardHostViewControllerTest extends SysuiTestCase { mTestableResources.addOverride( R.bool.can_use_one_handed_bouncer, true); mTestableResources.addOverride( - com.android.internal.R.bool.config_enableOneHandedKeyguard, true); + com.android.internal.R.bool.config_enableDynamicKeyguardPositioning, true); mKeyguardHostViewController.updateResources(); assertEquals( diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java index 9557d5cdb982..f5916e748f04 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java @@ -246,7 +246,8 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { boolean sysuiResourceCanUseOneHandedKeyguard, SecurityMode securityMode) { TestableResources testableResources = mContext.getOrCreateTestableResources(); - testableResources.addOverride(com.android.internal.R.bool.config_enableOneHandedKeyguard, + testableResources.addOverride( + com.android.internal.R.bool.config_enableDynamicKeyguardPositioning, deviceConfigCanUseOneHandedKeyguard); testableResources.addOverride(R.bool.can_use_one_handed_bouncer, sysuiResourceCanUseOneHandedKeyguard); diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java index 40ab10834ae4..7cb29215b5bf 100644 --- a/services/core/java/com/android/server/display/ColorFade.java +++ b/services/core/java/com/android/server/display/ColorFade.java @@ -93,6 +93,7 @@ final class ColorFade { private int mDisplayHeight; // real height, not rotated private SurfaceControl mSurfaceControl; private Surface mSurface; + private SurfaceControl mBLASTSurfaceControl; private BLASTBufferQueue mBLASTBufferQueue; private NaturalSurfaceLayout mSurfaceLayout; private EGLDisplay mEglDisplay; @@ -576,7 +577,7 @@ final class ColorFade { if (mMode == MODE_FADE) { builder.setColorLayer(); } else { - builder.setBLASTLayer(); + builder.setContainerLayer(); } mSurfaceControl = builder.build(); } catch (OutOfResourcesException ex) { @@ -592,7 +593,14 @@ final class ColorFade { mTransaction.apply(); if (mMode != MODE_FADE) { - mBLASTBufferQueue = new BLASTBufferQueue("ColorFade", mSurfaceControl, + final SurfaceControl.Builder b = new SurfaceControl.Builder() + .setName("ColorFade BLAST") + .setParent(mSurfaceControl) + .setHidden(false) + .setSecure(isSecure) + .setBLASTLayer(); + mBLASTSurfaceControl = b.build(); + mBLASTBufferQueue = new BLASTBufferQueue("ColorFade", mBLASTSurfaceControl, mDisplayWidth, mDisplayHeight, PixelFormat.TRANSLUCENT); mSurface = mBLASTBufferQueue.createSurface(); } @@ -723,10 +731,16 @@ final class ColorFade { mTransaction.remove(mSurfaceControl).apply(); if (mSurface != null) { mSurface.release(); - mBLASTBufferQueue.destroy(); mSurface = null; + } + + if (mBLASTSurfaceControl != null) { + mBLASTSurfaceControl.release(); + mBLASTSurfaceControl = null; + mBLASTBufferQueue.destroy(); mBLASTBufferQueue = null; } + mSurfaceControl = null; mSurfaceVisible = false; mSurfaceAlpha = 0f; diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index 314955b4ed4b..170564d145dc 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -422,7 +422,7 @@ public class DisplayDeviceConfig { if (configBrightnessDefault != null) { mBrightnessDefault = configBrightnessDefault.floatValue(); } else { - mBrightnessDefault = BRIGHTNESS_DEFAULT; + loadBrightnessDefaultFromConfigXml(); } } } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 4ad8797a14bf..52b05f2d112f 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -1362,6 +1362,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call + mBrightnessReasonTemp.toString(brightnessAdjustmentFlags) + "', previous reason: '" + mBrightnessReason + "'."); mBrightnessReason.set(mBrightnessReasonTemp); + } else if (mBrightnessReasonTemp.reason == BrightnessReason.REASON_MANUAL + && userSetBrightnessChanged) { + Slog.v(TAG, "Brightness [" + brightnessState + "] manual adjustment."); } // Update display white-balance. @@ -2021,7 +2024,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call || mPendingScreenBrightnessSetting < 0.0f)) { return false; } - if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) { + if (BrightnessSynchronizer.floatEquals( + mCurrentScreenBrightnessSetting, mPendingScreenBrightnessSetting)) { mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT; mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; return false; diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java index dc3dc468f763..ee799d502163 100644 --- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java +++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java @@ -19,6 +19,7 @@ package com.android.server.graphics.fonts; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.content.Context; import android.graphics.Typeface; import android.graphics.fonts.FontFamily; @@ -62,6 +63,7 @@ public final class FontManagerService extends IFontManager.Stub { private static final String FONT_FILES_DIR = "/data/fonts/files"; + @RequiresPermission(Manifest.permission.UPDATE_FONTS) @Override public FontConfig getFontConfig() { getContext().enforceCallingPermission(Manifest.permission.UPDATE_FONTS, @@ -69,28 +71,38 @@ public final class FontManagerService extends IFontManager.Stub { return getSystemFontConfig(); } + @RequiresPermission(Manifest.permission.UPDATE_FONTS) @Override public int updateFontFamily(@NonNull List<FontUpdateRequest> requests, int baseVersion) { - Preconditions.checkArgumentNonnegative(baseVersion); - Objects.requireNonNull(requests); - getContext().enforceCallingPermission(Manifest.permission.UPDATE_FONTS, - "UPDATE_FONTS permission required."); try { - update(baseVersion, requests); - return FontManager.RESULT_SUCCESS; - } catch (SystemFontException e) { - Slog.e(TAG, "Failed to update font family", e); - return e.getErrorCode(); + Preconditions.checkArgumentNonnegative(baseVersion); + Objects.requireNonNull(requests); + getContext().enforceCallingPermission(Manifest.permission.UPDATE_FONTS, + "UPDATE_FONTS permission required."); + try { + update(baseVersion, requests); + return FontManager.RESULT_SUCCESS; + } catch (SystemFontException e) { + Slog.e(TAG, "Failed to update font family", e); + return e.getErrorCode(); + } } finally { - for (FontUpdateRequest request : requests) { - ParcelFileDescriptor fd = request.getFd(); - if (fd != null) { - try { - fd.close(); - } catch (IOException e) { - Slog.w(TAG, "Failed to close fd", e); - } - } + closeFileDescriptors(requests); + } + } + + private static void closeFileDescriptors(@Nullable List<FontUpdateRequest> requests) { + // Make sure we close every passed FD, even if 'requests' is constructed incorrectly and + // some fields are null. + if (requests == null) return; + for (FontUpdateRequest request : requests) { + if (request == null) continue; + ParcelFileDescriptor fd = request.getFd(); + if (fd == null) continue; + try { + fd.close(); + } catch (IOException e) { + Slog.w(TAG, "Failed to close fd", e); } } } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java index 2969e53f2ba6..c340a2b77874 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java @@ -196,7 +196,7 @@ final class InputMethodSubtypeSwitchingController { final int numImes = imis.size(); for (int i = 0; i < numImes; ++i) { final InputMethodInfo imi = imis.get(i); - if (forImeMenu && !imi.showInInputMethodPicker()) { + if (forImeMenu && !imi.shouldShowInInputMethodPicker()) { continue; } final List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypeList = diff --git a/services/core/java/com/android/server/os/OWNERS b/services/core/java/com/android/server/os/OWNERS new file mode 100644 index 000000000000..19573323e5ad --- /dev/null +++ b/services/core/java/com/android/server/os/OWNERS @@ -0,0 +1,2 @@ +# Bugreporting +per-file Bugreport* = file:/platform/frameworks/native:/cmds/dumpstate/OWNERS diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java index 792753860358..9ea16d322c3c 100644 --- a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java +++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java @@ -19,7 +19,6 @@ package com.android.server.pm; import android.annotation.NonNull; import android.content.IntentFilter; -import com.android.server.WatchedIntentResolver; import com.android.server.utils.Snappable; import com.android.server.utils.SnapshotCache; diff --git a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java index bfddaea0dd75..bc65c3a7e20c 100644 --- a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java +++ b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java @@ -19,7 +19,6 @@ package com.android.server.pm; import android.annotation.NonNull; import android.content.IntentFilter; -import com.android.server.WatchedIntentResolver; import com.android.server.utils.Snappable; import com.android.server.utils.SnapshotCache; diff --git a/services/core/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java index 0aca6eec25fc..fc7680bad9d4 100644 --- a/services/core/java/com/android/server/pm/PreferredIntentResolver.java +++ b/services/core/java/com/android/server/pm/PreferredIntentResolver.java @@ -19,7 +19,6 @@ package com.android.server.pm; import android.annotation.NonNull; import android.content.IntentFilter; -import com.android.server.WatchedIntentResolver; import com.android.server.utils.Snappable; import com.android.server.utils.SnapshotCache; diff --git a/services/core/java/com/android/server/WatchedIntentResolver.java b/services/core/java/com/android/server/pm/WatchedIntentResolver.java index 0831c36d2bf6..1c3d884e3a98 100644 --- a/services/core/java/com/android/server/WatchedIntentResolver.java +++ b/services/core/java/com/android/server/pm/WatchedIntentResolver.java @@ -14,18 +14,20 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.pm; import android.annotation.NonNull; import android.annotation.Nullable; -import com.android.server.pm.WatchedIntentFilter; +import com.android.server.IntentResolver; import com.android.server.utils.Snappable; import com.android.server.utils.Watchable; import com.android.server.utils.WatchableImpl; import com.android.server.utils.Watcher; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; /** @@ -34,7 +36,8 @@ import java.util.List; * @param <R> The resolver type. * {@hide} */ -public abstract class WatchedIntentResolver<F extends Watchable, R extends Object> +public abstract class WatchedIntentResolver<F extends WatchedIntentFilter, + R extends WatchedIntentFilter> extends IntentResolver<F, R> implements Watchable, Snappable { @@ -116,11 +119,21 @@ public abstract class WatchedIntentResolver<F extends Watchable, R extends Objec onChanged(); } + // Sorts a List of IntentFilter objects into descending priority order. + @SuppressWarnings("rawtypes") + private static final Comparator<WatchedIntentFilter> sResolvePrioritySorter = + new Comparator<>() { + public int compare(WatchedIntentFilter o1, WatchedIntentFilter o2) { + final int q1 = o1.getPriority(); + final int q2 = o2.getPriority(); + return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0); + } + }; + @Override @SuppressWarnings("unchecked") protected void sortResults(List<R> results) { - super.sortResults(results); - onChanged(); + Collections.sort(results, sResolvePrioritySorter); } /** diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index c897c3ee4f42..c21f72e12605 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -1072,6 +1072,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { private void powerLongPress(long eventTime) { final int behavior = getResolvedLongPressOnPowerBehavior(); + Slog.d(TAG, "powerLongPress: eventTime=" + eventTime + + " mLongPressOnPowerBehavior=" + mLongPressOnPowerBehavior); switch (behavior) { case LONG_PRESS_POWER_NOTHING: diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index dec6460147cf..b27278c92679 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -289,12 +289,6 @@ public class RecentsAnimationController implements DeathRecipient { } } if (!behindSystemBars) { - // Make sure to update the correct IME parent in case that the IME parent - // may be computed as display layer when re-layout window happens during - // rotation but there is intermediate state that the bounds of task and - // the IME target's activity is not the same during rotating. - mDisplayContent.updateImeParent(); - // Hiding IME if IME window is not attached to app. // Since some windowing mode is not proper to snapshot Task with IME window // while the app transitioning to the next task (e.g. split-screen mode) diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml index de4698dcf3b2..985b2d5f24ba 100644 --- a/services/tests/wmtests/AndroidManifest.xml +++ b/services/tests/wmtests/AndroidManifest.xml @@ -41,6 +41,7 @@ <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" /> <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" /> + <uses-permission android:name="android.permission.CAPTURE_BLACKOUT_CONTENT"/> <!-- TODO: Remove largeHeap hack when memory leak is fixed (b/123984854) --> <application android:debuggable="true" @@ -75,6 +76,7 @@ <activity android:name="com.android.server.wm.ActivityOptionsTest$MainActivity" android:turnScreenOn="true" android:showWhenLocked="true" /> + <activity android:name="com.android.server.wm.ScreenshotTests$ScreenshotActivity" /> </application> <instrumentation diff --git a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java new file mode 100644 index 000000000000..f542e290c701 --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2021 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.server.wm; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import android.app.Activity; +import android.app.Instrumentation; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorSpace; +import android.graphics.GraphicBuffer; +import android.graphics.PixelFormat; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.platform.test.annotations.Presubmit; +import android.view.PointerIcon; +import android.view.SurfaceControl; +import android.view.WindowManager; + +import androidx.annotation.Nullable; +import androidx.test.filters.SmallTest; +import androidx.test.rule.ActivityTestRule; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Build/Install/Run: + * atest WmTests:ScreenshotTests + */ +@SmallTest +@Presubmit +public class ScreenshotTests { + private static final int BUFFER_WIDTH = 100; + private static final int BUFFER_HEIGHT = 100; + + private final Instrumentation mInstrumentation = getInstrumentation(); + + @Rule + public ActivityTestRule<ScreenshotActivity> mActivityRule = + new ActivityTestRule<>(ScreenshotActivity.class); + + private ScreenshotActivity mActivity; + + @Before + public void setup() { + mActivity = mActivityRule.getActivity(); + mInstrumentation.waitForIdleSync(); + } + + @Test + public void testScreenshotSecureLayers() { + SurfaceControl secureSC = new SurfaceControl.Builder() + .setName("SecureChildSurfaceControl") + .setBLASTLayer() + .setCallsite("makeSecureSurfaceControl") + .setSecure(true) + .build(); + + SurfaceControl.Transaction t = mActivity.addChildSc(secureSC); + mInstrumentation.waitForIdleSync(); + + GraphicBuffer buffer = GraphicBuffer.create(BUFFER_WIDTH, BUFFER_HEIGHT, + PixelFormat.RGBA_8888, + GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER + | GraphicBuffer.USAGE_SW_WRITE_RARELY); + + Canvas canvas = buffer.lockCanvas(); + canvas.drawColor(Color.RED); + buffer.unlockCanvasAndPost(canvas); + + t.show(secureSC) + .setBuffer(secureSC, buffer) + .setColorSpace(secureSC, ColorSpace.get(ColorSpace.Named.SRGB)) + .apply(true); + + SurfaceControl.LayerCaptureArgs args = new SurfaceControl.LayerCaptureArgs.Builder(secureSC) + .setCaptureSecureLayers(true) + .setChildrenOnly(false) + .build(); + SurfaceControl.ScreenshotHardwareBuffer hardwareBuffer = SurfaceControl.captureLayers(args); + assertNotNull(hardwareBuffer); + + Bitmap screenshot = hardwareBuffer.asBitmap(); + assertNotNull(screenshot); + + Bitmap swBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, false); + screenshot.recycle(); + + int numMatchingPixels = PixelChecker.getNumMatchingPixels(swBitmap, + new PixelColor(PixelColor.RED)); + long sizeOfBitmap = swBitmap.getWidth() * swBitmap.getHeight(); + boolean success = numMatchingPixels == sizeOfBitmap; + swBitmap.recycle(); + + assertTrue(success); + } + + public static class ScreenshotActivity extends Activity { + private static final long WAIT_TIMEOUT_S = 5; + private final Handler mHandler = new Handler(Looper.getMainLooper()); + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().getDecorView().setPointerIcon( + PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL)); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + + SurfaceControl.Transaction addChildSc(SurfaceControl surfaceControl) { + SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + CountDownLatch countDownLatch = new CountDownLatch(1); + mHandler.post(() -> { + t.merge(getWindow().getRootSurfaceControl().buildReparentTransaction( + surfaceControl)); + countDownLatch.countDown(); + }); + + try { + countDownLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS); + } catch (InterruptedException e) { + } + return t; + } + } + + public abstract static class PixelChecker { + static int getNumMatchingPixels(Bitmap bitmap, PixelColor pixelColor) { + int numMatchingPixels = 0; + for (int x = 0; x < bitmap.getWidth(); x++) { + for (int y = 0; y < bitmap.getHeight(); y++) { + int color = bitmap.getPixel(x, y); + if (matchesColor(pixelColor, color)) { + numMatchingPixels++; + } + } + } + return numMatchingPixels; + } + + static boolean matchesColor(PixelColor expectedColor, int color) { + final float red = Color.red(color); + final float green = Color.green(color); + final float blue = Color.blue(color); + final float alpha = Color.alpha(color); + + return alpha <= expectedColor.mMaxAlpha + && alpha >= expectedColor.mMinAlpha + && red <= expectedColor.mMaxRed + && red >= expectedColor.mMinRed + && green <= expectedColor.mMaxGreen + && green >= expectedColor.mMinGreen + && blue <= expectedColor.mMaxBlue + && blue >= expectedColor.mMinBlue; + } + } + + public static class PixelColor { + public static final int BLACK = 0xFF000000; + public static final int RED = 0xFF0000FF; + public static final int GREEN = 0xFF00FF00; + public static final int BLUE = 0xFFFF0000; + public static final int YELLOW = 0xFF00FFFF; + public static final int MAGENTA = 0xFFFF00FF; + public static final int WHITE = 0xFFFFFFFF; + + public static final int TRANSPARENT_RED = 0x7F0000FF; + public static final int TRANSPARENT_BLUE = 0x7FFF0000; + public static final int TRANSPARENT = 0x00000000; + + // Default to black + public short mMinAlpha; + public short mMaxAlpha; + public short mMinRed; + public short mMaxRed; + public short mMinBlue; + public short mMaxBlue; + public short mMinGreen; + public short mMaxGreen; + + public PixelColor(int color) { + short alpha = (short) ((color >> 24) & 0xFF); + short blue = (short) ((color >> 16) & 0xFF); + short green = (short) ((color >> 8) & 0xFF); + short red = (short) (color & 0xFF); + + mMinAlpha = (short) getMinValue(alpha); + mMaxAlpha = (short) getMaxValue(alpha); + mMinRed = (short) getMinValue(red); + mMaxRed = (short) getMaxValue(red); + mMinBlue = (short) getMinValue(blue); + mMaxBlue = (short) getMaxValue(blue); + mMinGreen = (short) getMinValue(green); + mMaxGreen = (short) getMaxValue(green); + } + + public PixelColor() { + this(BLACK); + } + + private int getMinValue(short color) { + return Math.max(color - 4, 0); + } + + private int getMaxValue(short color) { + return Math.min(color + 4, 0xFF); + } + } +} diff --git a/telephony/common/com/google/android/mms/pdu/PduParser.java b/telephony/common/com/google/android/mms/pdu/PduParser.java index 5340245ae869..677fe2f188a9 100755 --- a/telephony/common/com/google/android/mms/pdu/PduParser.java +++ b/telephony/common/com/google/android/mms/pdu/PduParser.java @@ -1550,6 +1550,11 @@ public class PduParser { if (cur < TEXT_MIN) { int length = parseValueLength(pduDataStream); int startPos = pduDataStream.available(); + if (length > startPos) { + Log.e(LOG_TAG, "parseContentType: Invalid length " + length + + " when available bytes are " + startPos); + return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*" + } pduDataStream.mark(1); temp = pduDataStream.read(); assert(-1 != temp); diff --git a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java index 44f96c5a987b..80b0dfeb8804 100644 --- a/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java +++ b/tests/UpdatableSystemFontTest/src/com/android/updatablesystemfont/UpdatableSystemFontTest.java @@ -20,6 +20,7 @@ import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; import static org.junit.Assume.assumeTrue; import static java.util.concurrent.TimeUnit.SECONDS; @@ -247,7 +248,6 @@ public class UpdatableSystemFontTest { assertThat(fontPathAfterReboot).isEqualTo(fontPath); } - @Test public void fdLeakTest() throws Exception { long originalOpenFontCount = @@ -273,6 +273,20 @@ public class UpdatableSystemFontTest { } } + @Test + public void fdLeakTest_withoutPermission() throws Exception { + Pattern patternEmojiVPlus1 = + Pattern.compile(Pattern.quote(TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF)); + byte[] signature = Files.readAllBytes(Paths.get(TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG)); + try (ParcelFileDescriptor fd = ParcelFileDescriptor.open( + new File(TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF), MODE_READ_ONLY)) { + assertThrows(SecurityException.class, + () -> updateFontFileWithoutPermission(fd, signature, 0)); + } + List<String> openFiles = getOpenFiles("system_server"); + assertThat(countMatch(openFiles, patternEmojiVPlus1)).isEqualTo(0); + } + private static String insertCert(String certPath) throws Exception { Pair<String, String> result; try (InputStream is = new FileInputStream(certPath)) { @@ -290,16 +304,21 @@ public class UpdatableSystemFontTest { try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(new File(fontPath), MODE_READ_ONLY)) { return SystemUtil.runWithShellPermissionIdentity(() -> { - FontConfig fontConfig = mFontManager.getFontConfig(); - return mFontManager.updateFontFamily( - new FontFamilyUpdateRequest.Builder() - .addFontFileUpdateRequest(new FontFileUpdateRequest(fd, signature)) - .build(), - fontConfig.getConfigVersion()); + int configVersion = mFontManager.getFontConfig().getConfigVersion(); + return updateFontFileWithoutPermission(fd, signature, configVersion); }); } } + private int updateFontFileWithoutPermission(ParcelFileDescriptor fd, byte[] signature, + int configVersion) { + return mFontManager.updateFontFamily( + new FontFamilyUpdateRequest.Builder() + .addFontFileUpdateRequest(new FontFileUpdateRequest(fd, signature)) + .build(), + configVersion); + } + private String getFontPath(String psName) { return SystemUtil.runWithShellPermissionIdentity(() -> { FontConfig fontConfig = mFontManager.getFontConfig(); |