diff options
Diffstat (limited to 'libs')
18 files changed, 237 insertions, 74 deletions
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index 0195f3df83a6..c5e79f87ca50 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -62,9 +62,9 @@ <string name="bubble_dismiss_text" msgid="8816558050659478158">"Bubble schließen"</string> <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Unterhaltung nicht als Bubble anzeigen"</string> <string name="bubbles_user_education_title" msgid="2112319053732691899">"Bubbles zum Chatten verwenden"</string> - <string name="bubbles_user_education_description" msgid="4215862563054175407">"Neue Unterhaltungen erscheinen als unverankerte Symbole, \"Bubbles\" genannt. Wenn du die Bubble öffnen möchtest, tippe sie an. Wenn du sie verschieben möchtest, zieh an ihr."</string> + <string name="bubbles_user_education_description" msgid="4215862563054175407">"Neue Unterhaltungen erscheinen als unverankerte Symbole, „Bubbles“ genannt. Wenn du eine Bubble öffnen möchtest, tippe sie an. Wenn du sie verschieben möchtest, zieh an ihr."</string> <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Bubble-Einstellungen festlegen"</string> - <string name="bubbles_user_education_manage" msgid="3460756219946517198">"Tippe auf \"Verwalten\", um Bubbles für diese App zu deaktivieren"</string> + <string name="bubbles_user_education_manage" msgid="3460756219946517198">"Tippe auf „Verwalten“, um Bubbles für diese App zu deaktivieren"</string> <string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string> <string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Keine kürzlich geschlossenen Bubbles"</string> <string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Hier werden aktuelle und geschlossene Bubbles angezeigt"</string> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index 34f75dab7a1b..c788a03a5b29 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -62,7 +62,7 @@ <string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignora bolla"</string> <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Non mettere la conversazione nella bolla"</string> <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatta utilizzando le bolle"</string> - <string name="bubbles_user_education_description" msgid="4215862563054175407">"Le nuove conversazioni vengono visualizzate come icone mobili o bolle. Tocca per aprire la bolla. Trascinala per spostarla."</string> + <string name="bubbles_user_education_description" msgid="4215862563054175407">"Le nuove conversazioni vengono mostrate come icone mobili o bolle. Tocca per aprire la bolla. Trascinala per spostarla."</string> <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Controlla le bolle quando vuoi"</string> <string name="bubbles_user_education_manage" msgid="3460756219946517198">"Tocca Gestisci per disattivare le bolle dall\'app"</string> <string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string> diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml index ef5ed00b4bda..36700bd81717 100644 --- a/libs/WindowManager/Shell/res/values-ja/strings.xml +++ b/libs/WindowManager/Shell/res/values-ja/strings.xml @@ -63,7 +63,7 @@ <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"会話をバブルで表示しない"</string> <string name="bubbles_user_education_title" msgid="2112319053732691899">"チャットでバブルを使う"</string> <string name="bubbles_user_education_description" msgid="4215862563054175407">"新しい会話はフローティング アイコン(バブル)として表示されます。タップするとバブルが開きます。ドラッグしてバブルを移動できます。"</string> - <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"いつでもバブルを管理"</string> + <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"バブルはいつでも管理可能"</string> <string name="bubbles_user_education_manage" msgid="3460756219946517198">"このアプリからのバブルを OFF にするには、[管理] をタップしてください"</string> <string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string> <string name="bubble_overflow_empty_title" msgid="2397251267073294968">"最近閉じたバブルはありません"</string> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index 8c8a56a773f7..dfd878f63283 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -368,6 +368,13 @@ public class BubbleController { return; } } + for (Bubble b : mBubbleData.getOverflowBubbles()) { + if (task.taskId == b.getTaskId()) { + promoteBubbleFromOverflow(b); + mBubbleData.setExpanded(true); + return; + } + } } }); @@ -815,7 +822,35 @@ public class BubbleController { setIsBubble(bubble, true /* isBubble */); } - @VisibleForTesting + /** + * Expands and selects the provided bubble as long as it already exists in the stack or the + * overflow. + * + * This is currently only used when opening a bubble via clicking on a conversation widget. + */ + public void expandStackAndSelectBubble(Bubble b) { + if (b == null) { + return; + } + if (mBubbleData.hasBubbleInStackWithKey(b.getKey())) { + // already in the stack + mBubbleData.setSelectedBubble(b); + mBubbleData.setExpanded(true); + } else if (mBubbleData.hasOverflowBubbleWithKey(b.getKey())) { + // promote it out of the overflow + promoteBubbleFromOverflow(b); + } + } + + /** + * Expands and selects a bubble based on the provided {@link BubbleEntry}. If no bubble + * exists for this entry, and it is able to bubble, a new bubble will be created. + * + * This is the method to use when opening a bubble via a notification or in a state where + * the device might not be unlocked. + * + * @param entry the entry to use for the bubble. + */ public void expandStackAndSelectBubble(BubbleEntry entry) { if (mIsStatusBarShade) { mNotifEntryToExpandOnShadeUnlock = null; @@ -1383,6 +1418,21 @@ public class BubbleController { } @Override + public void expandStackAndSelectBubble(Bubble bubble) { + mMainExecutor.execute(() -> { + BubbleController.this.expandStackAndSelectBubble(bubble); + }); + } + + @Override + @Nullable + public Bubble getBubbleWithShortcutId(String shortcutId) { + return mMainExecutor.executeBlockingForResult(() -> { + return BubbleController.this.mBubbleData.getAnyBubbleWithShortcutId(shortcutId); + }, Bubble.class); + } + + @Override public void onTaskbarChanged(Bundle b) { mMainExecutor.execute(() -> { BubbleController.this.onTaskbarChanged(b); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java index 69a741c674db..6f5cfd114688 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java @@ -26,6 +26,7 @@ import android.app.PendingIntent; import android.content.Context; import android.content.LocusId; import android.content.pm.ShortcutInfo; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -874,6 +875,34 @@ public class BubbleData { return b; } + /** @return any bubble (in the stack or the overflow) that matches the provided shortcutId. */ + @Nullable + Bubble getAnyBubbleWithShortcutId(String shortcutId) { + if (TextUtils.isEmpty(shortcutId)) { + return null; + } + for (int i = 0; i < mBubbles.size(); i++) { + Bubble bubble = mBubbles.get(i); + String bubbleShortcutId = bubble.getShortcutInfo() != null + ? bubble.getShortcutInfo().getId() + : bubble.getMetadataShortcutId(); + if (shortcutId.equals(bubbleShortcutId)) { + return bubble; + } + } + + for (int i = 0; i < mOverflowBubbles.size(); i++) { + Bubble bubble = mOverflowBubbles.get(i); + String bubbleShortcutId = bubble.getShortcutInfo() != null + ? bubble.getShortcutInfo().getId() + : bubble.getMetadataShortcutId(); + if (shortcutId.equals(bubbleShortcutId)) { + return bubble; + } + } + return null; + } + @VisibleForTesting(visibility = PRIVATE) @Nullable public Bubble getBubbleInStackWithKey(String key) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 16b8150467fd..c71f123459ec 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -50,7 +50,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; -import android.view.WindowInsets; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.widget.FrameLayout; @@ -1018,7 +1017,10 @@ public class BubbleStackView extends FrameLayout removeView(mDismissView); } mDismissView = new DismissView(getContext()); + int elevation = getResources().getDimensionPixelSize(R.dimen.bubble_elevation); + addView(mDismissView); + mDismissView.setElevation(elevation); final ContentResolver contentResolver = getContext().getContentResolver(); final int dismissRadius = Settings.Secure.getInt( @@ -1028,6 +1030,8 @@ public class BubbleStackView extends FrameLayout // MagnetizedObjects. mMagneticTarget = new MagnetizedObject.MagneticTarget( mDismissView.getCircle(), dismissRadius); + + mBubbleContainer.bringToFront(); } // TODO: Create ManageMenuView and move setup / animations there diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java index a93ce01dfc7b..c73b5eebc5c2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java @@ -118,6 +118,19 @@ public interface Bubbles { */ void expandStackAndSelectBubble(BubbleEntry entry); + /** + * Request the stack expand if needed, then select the specified Bubble as current. + * + * @param bubble the bubble to be selected + */ + void expandStackAndSelectBubble(Bubble bubble); + + /** + * @return a bubble that matches the provided shortcutId, if one exists. + */ + @Nullable + Bubble getBubbleWithShortcutId(String shortcutId); + /** Called for any taskbar changes. */ void onTaskbarChanged(Bundle b); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java index ee2202a48bf2..261ff2f8de83 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java @@ -550,12 +550,14 @@ public class LegacySplitScreenController implements DisplayController.OnDisplays update(mDisplayController.getDisplayContext( mContext.getDisplayId()).getResources().getConfiguration()); // Set resizable directly here because applyEnterSplit already resizes home stack. - mHomeStackResizable = mWindowManagerProxy.applyEnterSplit(mSplits, mSplitLayout); + mHomeStackResizable = mWindowManagerProxy.applyEnterSplit(mSplits, + mRotateSplitLayout != null ? mRotateSplitLayout : mSplitLayout); } public void prepareEnterSplitTransition(WindowContainerTransaction outWct) { // Set resizable directly here because buildEnterSplit already resizes home stack. - mHomeStackResizable = mWindowManagerProxy.buildEnterSplit(outWct, mSplits, mSplitLayout); + mHomeStackResizable = mWindowManagerProxy.buildEnterSplit(outWct, mSplits, + mRotateSplitLayout != null ? mRotateSplitLayout : mSplitLayout); } public void finishEnterSplitTransition(boolean minimized) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java index 49266ce1bb62..c275d50a5d56 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java @@ -71,6 +71,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController> "persist.debug.one_handed_offset_percentage"; private static final String ONE_HANDED_MODE_GESTURAL_OVERLAY = "com.android.internal.systemui.onehanded.gestural"; + private static final int OVERLAY_ENABLED_DELAY_MS = 250; static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode"; @@ -493,9 +494,11 @@ public class OneHandedController implements RemoteCallable<OneHandedController> setOneHandedEnabled(enabled); // Also checks swipe to notification settings since they all need gesture overlay. - setEnabledGesturalOverlay( + // Enabled overlay package may affect the current animation(e.g:Settings switch), + // so we delay 250ms to enabled overlay after switch animation finish + mMainExecutor.executeDelayed(() -> setEnabledGesturalOverlay( enabled || mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled( - mContext.getContentResolver(), mUserId)); + mContext.getContentResolver(), mUserId)), OVERLAY_ENABLED_DELAY_MS); } @VisibleForTesting diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java index 02451c30d4ef..f6b5889dda28 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java @@ -202,6 +202,7 @@ public class PhonePipMenuController implements PipMenuController { mSystemWindows.updateViewLayout(mPipMenuView, getPipMenuLayoutParams(MENU_WINDOW_TITLE, destinationBounds.width(), destinationBounds.height())); + updateMenuLayout(destinationBounds); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java index 604ebc08f42e..c42750d62dd4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java @@ -684,7 +684,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, // Intentionally resize here even if the current bounds match the destination bounds. // This is so all the proper callbacks are performed. mPipTaskOrganizer.scheduleAnimateResizePip(toBounds, duration, - TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND, mUpdateBoundsCallback); + TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND, null /* updateBoundsCallback */); setAnimatingToBounds(toBounds); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java index 32553f97c020..841edef9172f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java @@ -536,8 +536,9 @@ public class PipResizeGestureHandler { mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds, PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE, callback); } + final float magnetRadiusPercent = (float) mLastResizeBounds.width() / mMinSize.x / 2.f; mPipDismissTargetHandler - .setMagneticFieldRadiusPercent((float) mLastResizeBounds.width() / mMinSize.x); + .setMagneticFieldRadiusPercent(magnetRadiusPercent); mPipUiEventLogger.log( PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_RESIZE); } else { diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp index ee7b26058952..d86d9ee56f4c 100644 --- a/libs/hwui/jni/Typeface.cpp +++ b/libs/hwui/jni/Typeface.cpp @@ -204,10 +204,9 @@ static sk_sp<SkData> makeSkDataCached(const std::string& path, bool hasVerity) { return entry; } -static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSkia( - minikin::BufferReader* reader) { - const void* buffer = reader->data(); - size_t pos = reader->pos(); +static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader); + +static minikin::Font::TypefaceLoader* readMinikinFontSkia(minikin::BufferReader* reader) { // Advance reader's position. reader->skipString(); // fontPath reader->skip<int>(); // fontIndex @@ -217,60 +216,63 @@ static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSki reader->skip<uint32_t>(); // expectedFontRevision reader->skipString(); // expectedPostScriptName } - return [buffer, pos]() -> std::shared_ptr<minikin::MinikinFont> { - minikin::BufferReader fontReader(buffer, pos); - std::string_view fontPath = fontReader.readString(); - std::string path(fontPath.data(), fontPath.size()); - ATRACE_FORMAT("Loading font %s", path.c_str()); - int fontIndex = fontReader.read<int>(); - const minikin::FontVariation* axesPtr; - uint32_t axesCount; - std::tie(axesPtr, axesCount) = fontReader.readArray<minikin::FontVariation>(); - bool hasVerity = static_cast<bool>(fontReader.read<int8_t>()); - uint32_t expectedFontRevision; - std::string_view expectedPostScriptName; - if (hasVerity) { - expectedFontRevision = fontReader.read<uint32_t>(); - expectedPostScriptName = fontReader.readString(); - } - sk_sp<SkData> data = makeSkDataCached(path, hasVerity); - if (data.get() == nullptr) { - // This may happen if: - // 1. When the process failed to open the file (e.g. invalid path or permission). - // 2. When the process failed to map the file (e.g. hitting max_map_count limit). - ALOGE("Failed to make SkData from file name: %s", path.c_str()); + return &loadMinikinFontSkia; +} + +static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader reader) { + std::string_view fontPath = reader.readString(); + std::string path(fontPath.data(), fontPath.size()); + ATRACE_FORMAT("Loading font %s", path.c_str()); + int fontIndex = reader.read<int>(); + const minikin::FontVariation* axesPtr; + uint32_t axesCount; + std::tie(axesPtr, axesCount) = reader.readArray<minikin::FontVariation>(); + bool hasVerity = static_cast<bool>(reader.read<int8_t>()); + uint32_t expectedFontRevision; + std::string_view expectedPostScriptName; + if (hasVerity) { + expectedFontRevision = reader.read<uint32_t>(); + expectedPostScriptName = reader.readString(); + } + sk_sp<SkData> data = makeSkDataCached(path, hasVerity); + if (data.get() == nullptr) { + // This may happen if: + // 1. When the process failed to open the file (e.g. invalid path or permission). + // 2. When the process failed to map the file (e.g. hitting max_map_count limit). + ALOGE("Failed to make SkData from file name: %s", path.c_str()); + return nullptr; + } + const void* fontPtr = data->data(); + size_t fontSize = data->size(); + if (hasVerity) { + // Verify font metadata if verity is enabled. + minikin::FontFileParser parser(fontPtr, fontSize, fontIndex); + std::optional<uint32_t> revision = parser.getFontRevision(); + if (!revision.has_value() || revision.value() != expectedFontRevision) { + LOG_ALWAYS_FATAL("Wrong font revision: %s", path.c_str()); return nullptr; } - const void* fontPtr = data->data(); - size_t fontSize = data->size(); - if (hasVerity) { - // Verify font metadata if verity is enabled. - minikin::FontFileParser parser(fontPtr, fontSize, fontIndex); - std::optional<uint32_t> revision = parser.getFontRevision(); - if (!revision.has_value() || revision.value() != expectedFontRevision) { - LOG_ALWAYS_FATAL("Wrong font revision: %s", path.c_str()); - return nullptr; - } - std::optional<std::string> psName = parser.getPostScriptName(); - if (!psName.has_value() || psName.value() != expectedPostScriptName) { - LOG_ALWAYS_FATAL("Wrong PostScript name: %s", path.c_str()); - return nullptr; - } - } - std::vector<minikin::FontVariation> axes(axesPtr, axesPtr + axesCount); - std::shared_ptr<minikin::MinikinFont> minikinFont = - fonts::createMinikinFontSkia(std::move(data), fontPath, fontPtr, fontSize, - fontIndex, axes); - if (minikinFont == nullptr) { - ALOGE("Failed to create MinikinFontSkia: %s", path.c_str()); + std::optional<std::string> psName = parser.getPostScriptName(); + if (!psName.has_value() || psName.value() != expectedPostScriptName) { + LOG_ALWAYS_FATAL("Wrong PostScript name: %s", path.c_str()); return nullptr; } - return minikinFont; - }; + } + std::vector<minikin::FontVariation> axes(axesPtr, axesPtr + axesCount); + std::shared_ptr<minikin::MinikinFont> minikinFont = fonts::createMinikinFontSkia( + std::move(data), fontPath, fontPtr, fontSize, fontIndex, axes); + if (minikinFont == nullptr) { + ALOGE("Failed to create MinikinFontSkia: %s", path.c_str()); + return nullptr; + } + return minikinFont; } static void writeMinikinFontSkia(minikin::BufferWriter* writer, const minikin::MinikinFont* typeface) { + // When you change the format of font metadata, please update code to parse + // typefaceMetadataReader() in + // frameworks/base/libs/hwui/jni/fonts/Font.cpp too. const std::string& path = typeface->GetFontPath(); writer->writeString(path); writer->write<int>(typeface->GetFontIndex()); diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp index bd3b7c93466c..09be630dc741 100644 --- a/libs/hwui/jni/fonts/Font.cpp +++ b/libs/hwui/jni/fonts/Font.cpp @@ -192,7 +192,7 @@ static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong // Critical Native static jlong Font_getMinikinFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); - return reinterpret_cast<jlong>(font->font->typeface().get()); + return reinterpret_cast<jlong>(font->font.get()); } // Critical Native @@ -224,12 +224,21 @@ static jlong Font_getReleaseNativeFontFunc(CRITICAL_JNI_PARAMS) { // Fast Native static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); - const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); - const std::string& path = minikinFont->GetFontPath(); - if (path.empty()) { - return nullptr; + minikin::BufferReader reader = font->font->typefaceMetadataReader(); + if (reader.data() != nullptr) { + std::string path = std::string(reader.readString()); + if (path.empty()) { + return nullptr; + } + return env->NewStringUTF(path.c_str()); + } else { + const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); + const std::string& path = minikinFont->GetFontPath(); + if (path.empty()) { + return nullptr; + } + return env->NewStringUTF(path.c_str()); } - return env->NewStringUTF(path.c_str()); } // Fast Native @@ -257,22 +266,43 @@ static jint Font_getPackedStyle(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { // Critical Native static jint Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); - const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); - return minikinFont->GetFontIndex(); + minikin::BufferReader reader = font->font->typefaceMetadataReader(); + if (reader.data() != nullptr) { + reader.skipString(); // fontPath + return reader.read<int>(); + } else { + const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); + return minikinFont->GetFontIndex(); + } } // Critical Native static jint Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); - const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); - return minikinFont->GetAxes().size(); + minikin::BufferReader reader = font->font->typefaceMetadataReader(); + if (reader.data() != nullptr) { + reader.skipString(); // fontPath + reader.skip<int>(); // fontIndex + return reader.readArray<minikin::FontVariation>().second; + } else { + const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); + return minikinFont->GetAxes().size(); + } } // Critical Native static jlong Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr, jint index) { FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr); - const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); - minikin::FontVariation var = minikinFont->GetAxes().at(index); + minikin::BufferReader reader = font->font->typefaceMetadataReader(); + minikin::FontVariation var; + if (reader.data() != nullptr) { + reader.skipString(); // fontPath + reader.skip<int>(); // fontIndex + var = reader.readArray<minikin::FontVariation>().first[index]; + } else { + const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface(); + var = minikinFont->GetAxes().at(index); + } uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value); return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary); } diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp index 46e806081c0c..ded2b06fb3cf 100644 --- a/libs/hwui/renderthread/CacheManager.cpp +++ b/libs/hwui/renderthread/CacheManager.cpp @@ -210,6 +210,14 @@ void CacheManager::onFrameCompleted() { } } +void CacheManager::performDeferredCleanup(nsecs_t cleanupOlderThanMillis) { + if (mGrContext) { + mGrContext->performDeferredCleanup( + std::chrono::milliseconds(cleanupOlderThanMillis), + /* scratchResourcesOnly */true); + } +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h index 713ea990ff23..af82672c6f23 100644 --- a/libs/hwui/renderthread/CacheManager.h +++ b/libs/hwui/renderthread/CacheManager.h @@ -23,6 +23,7 @@ #include <SkSurface.h> #include <utils/String8.h> #include <vector> +#include "utils/TimeUtils.h" namespace android { @@ -53,6 +54,8 @@ public: size_t getBackgroundCacheSize() const { return mBackgroundResourceBytes; } void onFrameCompleted(); + void performDeferredCleanup(nsecs_t cleanupOlderThanMillis); + private: friend class RenderThread; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index a0d93e928876..8bfc2c14ad7c 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -461,6 +461,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy } void CanvasContext::stopDrawing() { + cleanupResources(); mRenderThread.removeFrameCallback(this); mAnimationContext->pauseAnimators(); mGenerationID++; @@ -619,10 +620,25 @@ nsecs_t CanvasContext::draw() { } } + cleanupResources(); mRenderThread.cacheManager().onFrameCompleted(); return mCurrentFrameInfo->get(FrameInfoIndex::DequeueBufferDuration); } +void CanvasContext::cleanupResources() { + auto& tracker = mJankTracker.frames(); + auto size = tracker.size(); + auto capacity = tracker.capacity(); + if (size == capacity) { + nsecs_t nowNanos = systemTime(SYSTEM_TIME_MONOTONIC); + nsecs_t frameCompleteNanos = + tracker[0].get(FrameInfoIndex::FrameCompleted); + nsecs_t frameDiffNanos = nowNanos - frameCompleteNanos; + nsecs_t cleanupMillis = ns2ms(std::max(frameDiffNanos, 10_s)); + mRenderThread.cacheManager().performDeferredCleanup(cleanupMillis); + } +} + void CanvasContext::reportMetricsWithPresentTime() { if (mFrameMetricsReporter == nullptr) { return; diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 6f90e81e51b0..4bdc2514db8c 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -312,6 +312,7 @@ private: bool mExpectSurfaceStats = false; std::function<void(int64_t, int64_t, int64_t)> mASurfaceTransactionCallback; + void cleanupResources(); }; } /* namespace renderthread */ |