From 9325f9b97ece89498653b0f21b3ec7aceff5e566 Mon Sep 17 00:00:00 2001 From: Joanne Chung Date: Thu, 17 Feb 2022 23:58:43 +0800 Subject: [PATCH] Fix system toolbar doesn't use correct theme. The toolbar should set the theme to the app's theme. Because the service cannot get the application context, we should pass this information from application to service. Bug: 218833400 Test: manual. Use light/dark theme for app, the toolbar shows with the same theme Test: atest TextViewIntegrationTest Test: atest android.widget.TextViewActivityTest Change-Id: I6d4e4e117c680ce57e760a87987059eded09b2bc --- .../DefaultSelectionToolbarRenderService.java | 2 +- .../RemoteSelectionToolbar.java | 13 ++----- .../view/selectiontoolbar/ShowInfo.java | 39 +++++++++++++++---- .../RemoteFloatingToolbarPopup.java | 12 +++++- 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/core/java/android/service/selectiontoolbar/DefaultSelectionToolbarRenderService.java b/core/java/android/service/selectiontoolbar/DefaultSelectionToolbarRenderService.java index f028ed3e6b002..ad73a53cfd87f 100644 --- a/core/java/android/service/selectiontoolbar/DefaultSelectionToolbarRenderService.java +++ b/core/java/android/service/selectiontoolbar/DefaultSelectionToolbarRenderService.java @@ -69,7 +69,7 @@ public final class DefaultSelectionToolbarRenderService extends SelectionToolbar if (mToolbarCache.indexOfKey(callingUid) < 0) { RemoteSelectionToolbar toolbar = new RemoteSelectionToolbar(this, - widgetToken, showInfo.getHostInputToken(), + widgetToken, showInfo, callbackWrapper, this::transferTouch); mToolbarCache.put(callingUid, new Pair<>(widgetToken, toolbar)); } diff --git a/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java b/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java index d75fbc0c64e0d..95bcda5f7c55b 100644 --- a/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java +++ b/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java @@ -22,7 +22,6 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; -import android.content.res.TypedArray; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.AnimatedVectorDrawable; @@ -162,15 +161,14 @@ final class RemoteSelectionToolbar { private final Rect mTempContentRectForRoot = new Rect(); private final int[] mTempCoords = new int[2]; - RemoteSelectionToolbar(Context context, long selectionToolbarToken, IBinder hostInputToken, + RemoteSelectionToolbar(Context context, long selectionToolbarToken, ShowInfo showInfo, SelectionToolbarRenderService.RemoteCallbackWrapper callbackWrapper, SelectionToolbarRenderService.TransferTouchListener transferTouchListener) { - mContext = applyDefaultTheme(context); + mContext = applyDefaultTheme(context, showInfo.isIsLightTheme()); mSelectionToolbarToken = selectionToolbarToken; mCallbackWrapper = callbackWrapper; mTransferTouchListener = transferTouchListener; - mHostInputToken = hostInputToken; - + mHostInputToken = showInfo.getHostInputToken(); mContentContainer = createContentContainer(mContext); mMarginHorizontal = mContext.getResources() .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin); @@ -1359,12 +1357,9 @@ final class RemoteSelectionToolbar { /** * Returns a re-themed context with controlled look and feel for views. */ - private static Context applyDefaultTheme(Context originalContext) { - TypedArray a = originalContext.obtainStyledAttributes(new int[]{R.attr.isLightTheme}); - boolean isLightTheme = a.getBoolean(0, true); + private static Context applyDefaultTheme(Context originalContext, boolean isLightTheme) { int themeId = isLightTheme ? R.style.Theme_DeviceDefault_Light : R.style.Theme_DeviceDefault; - a.recycle(); return new ContextThemeWrapper(originalContext, themeId); } diff --git a/core/java/android/view/selectiontoolbar/ShowInfo.java b/core/java/android/view/selectiontoolbar/ShowInfo.java index 594b6bc7400a0..08d6db52008c6 100644 --- a/core/java/android/view/selectiontoolbar/ShowInfo.java +++ b/core/java/android/view/selectiontoolbar/ShowInfo.java @@ -75,6 +75,11 @@ public final class ShowInfo implements Parcelable { @NonNull private final IBinder mHostInputToken; + /** + * If the host application uses light theme. + */ + private final boolean mIsLightTheme; + // Code below generated by codegen v1.0.23. @@ -109,6 +114,8 @@ public final class ShowInfo implements Parcelable { * @param hostInputToken * The host application's input token, this allows the remote render service to transfer * the touch focus to the host application. + * @param isLightTheme + * If the host application uses light theme. */ @DataClass.Generated.Member public ShowInfo( @@ -118,7 +125,8 @@ public final class ShowInfo implements Parcelable { @NonNull Rect contentRect, int suggestedWidth, @NonNull Rect viewPortOnScreen, - @NonNull IBinder hostInputToken) { + @NonNull IBinder hostInputToken, + boolean isLightTheme) { this.mWidgetToken = widgetToken; this.mLayoutRequired = layoutRequired; this.mMenuItems = menuItems; @@ -134,6 +142,7 @@ public final class ShowInfo implements Parcelable { this.mHostInputToken = hostInputToken; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mHostInputToken); + this.mIsLightTheme = isLightTheme; // onConstructed(); // You can define this method to get a callback } @@ -196,6 +205,14 @@ public final class ShowInfo implements Parcelable { return mHostInputToken; } + /** + * If the host application uses light theme. + */ + @DataClass.Generated.Member + public boolean isIsLightTheme() { + return mIsLightTheme; + } + @Override @DataClass.Generated.Member public String toString() { @@ -209,7 +226,8 @@ public final class ShowInfo implements Parcelable { "contentRect = " + mContentRect + ", " + "suggestedWidth = " + mSuggestedWidth + ", " + "viewPortOnScreen = " + mViewPortOnScreen + ", " + - "hostInputToken = " + mHostInputToken + + "hostInputToken = " + mHostInputToken + ", " + + "isLightTheme = " + mIsLightTheme + " }"; } @@ -232,7 +250,8 @@ public final class ShowInfo implements Parcelable { && java.util.Objects.equals(mContentRect, that.mContentRect) && mSuggestedWidth == that.mSuggestedWidth && java.util.Objects.equals(mViewPortOnScreen, that.mViewPortOnScreen) - && java.util.Objects.equals(mHostInputToken, that.mHostInputToken); + && java.util.Objects.equals(mHostInputToken, that.mHostInputToken) + && mIsLightTheme == that.mIsLightTheme; } @Override @@ -249,6 +268,7 @@ public final class ShowInfo implements Parcelable { _hash = 31 * _hash + mSuggestedWidth; _hash = 31 * _hash + java.util.Objects.hashCode(mViewPortOnScreen); _hash = 31 * _hash + java.util.Objects.hashCode(mHostInputToken); + _hash = 31 * _hash + Boolean.hashCode(mIsLightTheme); return _hash; } @@ -258,9 +278,10 @@ public final class ShowInfo implements Parcelable { // You can override field parcelling by defining methods like: // void parcelFieldName(Parcel dest, int flags) { ... } - byte flg = 0; + int flg = 0; if (mLayoutRequired) flg |= 0x2; - dest.writeByte(flg); + if (mIsLightTheme) flg |= 0x80; + dest.writeInt(flg); dest.writeLong(mWidgetToken); dest.writeParcelableList(mMenuItems, flags); dest.writeTypedObject(mContentRect, flags); @@ -280,8 +301,9 @@ public final class ShowInfo implements Parcelable { // You can override field unparcelling by defining methods like: // static FieldType unparcelFieldName(Parcel in) { ... } - byte flg = in.readByte(); + int flg = in.readInt(); boolean layoutRequired = (flg & 0x2) != 0; + boolean isLightTheme = (flg & 0x80) != 0; long widgetToken = in.readLong(); List menuItems = new java.util.ArrayList<>(); in.readParcelableList(menuItems, ToolbarMenuItem.class.getClassLoader()); @@ -305,6 +327,7 @@ public final class ShowInfo implements Parcelable { this.mHostInputToken = hostInputToken; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mHostInputToken); + this.mIsLightTheme = isLightTheme; // onConstructed(); // You can define this method to get a callback } @@ -324,10 +347,10 @@ public final class ShowInfo implements Parcelable { }; @DataClass.Generated( - time = 1643186262604L, + time = 1645108384245L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/view/selectiontoolbar/ShowInfo.java", - inputSignatures = "private final long mWidgetToken\nprivate final boolean mLayoutRequired\nprivate final @android.annotation.NonNull java.util.List mMenuItems\nprivate final @android.annotation.NonNull android.graphics.Rect mContentRect\nprivate final int mSuggestedWidth\nprivate final @android.annotation.NonNull android.graphics.Rect mViewPortOnScreen\nprivate final @android.annotation.NonNull android.os.IBinder mHostInputToken\nclass ShowInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)") + inputSignatures = "private final long mWidgetToken\nprivate final boolean mLayoutRequired\nprivate final @android.annotation.NonNull java.util.List mMenuItems\nprivate final @android.annotation.NonNull android.graphics.Rect mContentRect\nprivate final int mSuggestedWidth\nprivate final @android.annotation.NonNull android.graphics.Rect mViewPortOnScreen\nprivate final @android.annotation.NonNull android.os.IBinder mHostInputToken\nprivate final boolean mIsLightTheme\nclass ShowInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)") @Deprecated private void __metadata() {} diff --git a/core/java/com/android/internal/widget/floatingtoolbar/RemoteFloatingToolbarPopup.java b/core/java/com/android/internal/widget/floatingtoolbar/RemoteFloatingToolbarPopup.java index 8c2eb1044e012..8787c39458b9f 100644 --- a/core/java/com/android/internal/widget/floatingtoolbar/RemoteFloatingToolbarPopup.java +++ b/core/java/com/android/internal/widget/floatingtoolbar/RemoteFloatingToolbarPopup.java @@ -23,6 +23,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UiThread; import android.content.Context; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -107,6 +108,7 @@ public final class RemoteFloatingToolbarPopup implements FloatingToolbarPopup { private int mSuggestedWidth; private final Rect mScreenViewPort = new Rect(); private boolean mWidthChanged = true; + private final boolean mIsLightTheme; private final int[] mCoordsOnScreen = new int[2]; private final int[] mCoordsOnWindow = new int[2]; @@ -116,9 +118,17 @@ public final class RemoteFloatingToolbarPopup implements FloatingToolbarPopup { mPopupWindow = createPopupWindow(context); mSelectionToolbarManager = context.getSystemService(SelectionToolbarManager.class); mSelectionToolbarCallback = new SelectionToolbarCallbackImpl(this); + mIsLightTheme = isLightTheme(context); mFloatingToolbarToken = NO_TOOLBAR_ID; } + private boolean isLightTheme(Context context) { + TypedArray a = context.obtainStyledAttributes(new int[]{R.attr.isLightTheme}); + boolean isLightTheme = a.getBoolean(0, true); + a.recycle(); + return isLightTheme; + } + @UiThread @Override public void show(List menuItems, @@ -155,7 +165,7 @@ public final class RemoteFloatingToolbarPopup implements FloatingToolbarPopup { contentRect, suggestWidth, mScreenViewPort, - mParent.getViewRootImpl().getInputToken()); + mParent.getViewRootImpl().getInputToken(), mIsLightTheme); if (DEBUG) { Log.v(FloatingToolbar.FLOATING_TOOLBAR_TAG, "RemoteFloatingToolbarPopup.show() for " + showInfo);