diff options
Diffstat (limited to 'libs')
53 files changed, 727 insertions, 476 deletions
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml index 14b0fd9db609..21172e2267bc 100644 --- a/libs/WindowManager/Shell/res/values-am/strings.xml +++ b/libs/WindowManager/Shell/res/values-am/strings.xml @@ -32,23 +32,23 @@ <string name="accessibility_action_pip_resize" msgid="4623966104749543182">"መጠን ይቀይሩ"</string> <string name="accessibility_action_pip_stash" msgid="4060775037619702641">"Stash"</string> <string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Unstash"</string> - <string name="dock_forced_resizable" msgid="7429086980048964687">"መተግበሪያ ከተከፈለ ማያ ገፅ ጋር ላይሠራ ይችላል"</string> + <string name="dock_forced_resizable" msgid="7429086980048964687">"መተግበሪያ ከተከፈለ ማያ ገጽ ጋር ላይሠራ ይችላል"</string> <string name="dock_non_resizeble_failed_to_dock_text" msgid="2733543750291266047">"መተግበሪያው የተከፈለ ማያ ገጽን አይደግፍም"</string> <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"ይህ መተግበሪያ መከፈት የሚችለው በ1 መስኮት ብቻ ነው።"</string> <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"መተግበሪያ በሁለተኛ ማሳያ ላይ ላይሠራ ይችላል።"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"መተግበሪያ በሁለተኛ ማሳያዎች ላይ ማስጀመርን አይደግፍም።"</string> - <string name="accessibility_divider" msgid="6407584574218956849">"የተከፈለ የማያ ገፅ ከፋይ"</string> - <string name="divider_title" msgid="1963391955593749442">"የተከፈለ የማያ ገፅ ከፋይ"</string> - <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"የግራ ሙሉ ማያ ገፅ"</string> + <string name="accessibility_divider" msgid="6407584574218956849">"የተከፈለ የማያ ገጽ ከፋይ"</string> + <string name="divider_title" msgid="1963391955593749442">"የተከፈለ የማያ ገጽ ከፋይ"</string> + <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"የግራ ሙሉ ማያ ገጽ"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ግራ 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ግራ 50%"</string> <string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"ግራ 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"የቀኝ ሙሉ ማያ ገፅ"</string> - <string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"የላይ ሙሉ ማያ ገፅ"</string> + <string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"የቀኝ ሙሉ ማያ ገጽ"</string> + <string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"የላይ ሙሉ ማያ ገጽ"</string> <string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"ከላይ 70%"</string> <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ከላይ 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ከላይ 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"የታች ሙሉ ማያ ገፅ"</string> + <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"የታች ሙሉ ማያ ገጽ"</string> <string name="accessibility_split_left" msgid="1713683765575562458">"ወደ ግራ ከፋፍል"</string> <string name="accessibility_split_right" msgid="8441001008181296837">"ወደ ቀኝ ከፋፍል"</string> <string name="accessibility_split_top" msgid="2789329702027147146">"ወደ ላይ ከፋፍል"</string> @@ -84,8 +84,8 @@ <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"አልተስተካከለም?\nለማህደር መታ ያድርጉ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ምንም የካሜራ ችግሮች የሉም? ለማሰናበት መታ ያድርጉ።"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ተጨማሪ ይመልከቱ እና ያድርጉ"</string> - <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"ለተከፈለ ማያ ገፅ ሌላ መተግበሪያ ይጎትቱ"</string> - <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ቦታውን ለመቀየር ከመተግበሪያው ውጭ ሁለቴ መታ ያድርጉ"</string> + <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"ለተከፈለ ማያ ገጽ ሌላ መተግበሪያ ይጎትቱ"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ቦታውን ለመቀየር ከመተግበሪያው ውጪ ሁለቴ መታ ያድርጉ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ገባኝ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ለተጨማሪ መረጃ ይዘርጉ።"</string> <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"ለተሻለ ዕይታ እንደገና ይጀመር?"</string> @@ -102,11 +102,11 @@ <string name="app_icon_text" msgid="2823268023931811747">"የመተግበሪያ አዶ"</string> <string name="fullscreen_text" msgid="1162316685217676079">"ሙሉ ማያ"</string> <string name="desktop_text" msgid="1077633567027630454">"የዴስክቶፕ ሁነታ"</string> - <string name="split_screen_text" msgid="1396336058129570886">"የተከፈለ ማያ ገፅ"</string> + <string name="split_screen_text" msgid="1396336058129570886">"የተከፈለ ማያ ገጽ"</string> <string name="more_button_text" msgid="3655388105592893530">"ተጨማሪ"</string> <string name="float_button_text" msgid="9221657008391364581">"ተንሳፋፊ"</string> <string name="select_text" msgid="5139083974039906583">"ምረጥ"</string> - <string name="screenshot_text" msgid="1477704010087786671">"ቅጽበታዊ ገፅ ዕይታ"</string> + <string name="screenshot_text" msgid="1477704010087786671">"ቅጽበታዊ ገጽ እይታ"</string> <string name="close_text" msgid="4986518933445178928">"ዝጋ"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"ምናሌ ዝጋ"</string> <string name="expand_menu_text" msgid="3847736164494181168">"ምናሌን ክፈት"</string> diff --git a/libs/WindowManager/Shell/res/values-am/strings_tv.xml b/libs/WindowManager/Shell/res/values-am/strings_tv.xml index 84c1c6763d43..a6be57889a4e 100644 --- a/libs/WindowManager/Shell/res/values-am/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-am/strings_tv.xml @@ -20,7 +20,7 @@ <string name="notification_channel_tv_pip" msgid="2576686079160402435">"ሥዕል-ላይ-ሥዕል"</string> <string name="pip_notification_unknown_title" msgid="2729870284350772311">"(ርዕስ የሌለው ፕሮግራም)"</string> <string name="pip_close" msgid="2955969519031223530">"ዝጋ"</string> - <string name="pip_fullscreen" msgid="7278047353591302554">"ሙሉ ማያ ገፅ"</string> + <string name="pip_fullscreen" msgid="7278047353591302554">"ሙሉ ማያ ገጽ"</string> <string name="pip_move" msgid="158770205886688553">"ውሰድ"</string> <string name="pip_expand" msgid="1051966011679297308">"ዘርጋ"</string> <string name="pip_collapse" msgid="3903295106641385962">"ሰብስብ"</string> diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml index c415c868ac04..8de9d11def2b 100644 --- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml +++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml @@ -89,7 +89,7 @@ <string name="letterbox_education_got_it" msgid="4057634570866051177">"Važi"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite za još informacija."</string> <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Želite li da restartujete radi boljeg prikaza?"</string> - <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Možete da restartujete aplikaciju da bi izgledala bolje na ekranu, ali možete da izgubite napredak ili nesačuvane promene"</string> + <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Možete da restartujete aplikaciju da bi izgledala bolje na ekranu, s tim što možete da izgubite ono što ste uradili ili nesačuvane promene, ako ih ima"</string> <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Otkaži"</string> <string name="letterbox_restart_restart" msgid="8529976234412442973">"Restartuj"</string> <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ne prikazuj ponovo"</string> diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml index ac22b8569e16..70e29705806f 100644 --- a/libs/WindowManager/Shell/res/values-cs/strings.xml +++ b/libs/WindowManager/Shell/res/values-cs/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Bublina"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Spravovat"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bublina byla zavřena."</string> - <string name="restart_button_description" msgid="6712141648865547958">"Pokud je problém se zobrazením aplikace, klepněte na ni a restartujte ji."</string> + <string name="restart_button_description" msgid="6712141648865547958">"Klepnutím tuto aplikaci kvůli lepšímu zobrazení restartujete."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problémy s fotoaparátem?\nKlepnutím vyřešíte"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nepomohlo to?\nKlepnutím se vrátíte"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Žádné problémy s fotoaparátem? Klepnutím zavřete."</string> diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index c17f97fbad0f..6ce475aa3c84 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -20,7 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Schließen"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Maximieren"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Einstellungen"</string> - <string name="pip_phone_enter_split" msgid="7042877263880641911">"Splitscreen aktivieren"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"„Geteilter Bildschirm“ aktivieren"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string> <string name="pip_menu_accessibility_title" msgid="8129016817688656249">"Menü „Bild im Bild“"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ist in Bild im Bild"</string> @@ -32,8 +32,8 @@ <string name="accessibility_action_pip_resize" msgid="4623966104749543182">"Größe anpassen"</string> <string name="accessibility_action_pip_stash" msgid="4060775037619702641">"In Stash legen"</string> <string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Aus Stash entfernen"</string> - <string name="dock_forced_resizable" msgid="7429086980048964687">"Die App funktioniert im Splitscreen-Modus unter Umständen nicht"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="2733543750291266047">"Splitscreen wird in dieser App nicht unterstützt"</string> + <string name="dock_forced_resizable" msgid="7429086980048964687">"Die App funktioniert bei geteiltem Bildschirm unter Umständen nicht"</string> + <string name="dock_non_resizeble_failed_to_dock_text" msgid="2733543750291266047">"„Geteilter Bildschirm“ wird in dieser App nicht unterstützt"</string> <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Diese App kann nur in einem einzigen Fenster geöffnet werden."</string> <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Die App funktioniert auf einem sekundären Display möglicherweise nicht."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Die App unterstützt den Start auf sekundären Displays nicht."</string> @@ -84,7 +84,7 @@ <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Das Problem ist nicht behoben?\nZum Rückgängigmachen tippen."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Keine Probleme mit der Kamera? Zum Schließen tippen."</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Mehr sehen und erledigen"</string> - <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Für Splitscreen-Modus weitere App hineinziehen"</string> + <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Weitere App hineinziehen, um den Bildschirm zu teilen"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Außerhalb einer App doppeltippen, um die Position zu ändern"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ok"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Für weitere Informationen maximieren."</string> @@ -102,12 +102,13 @@ <string name="app_icon_text" msgid="2823268023931811747">"App-Symbol"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Vollbild"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string> - <string name="split_screen_text" msgid="1396336058129570886">"Splitscreen"</string> + <string name="split_screen_text" msgid="1396336058129570886">"Geteilter Bildschirm"</string> <string name="more_button_text" msgid="3655388105592893530">"Mehr"</string> <string name="float_button_text" msgid="9221657008391364581">"Frei schwebend"</string> <string name="select_text" msgid="5139083974039906583">"Auswählen"</string> <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string> <string name="close_text" msgid="4986518933445178928">"Schließen"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Menü schließen"</string> - <string name="expand_menu_text" msgid="3847736164494181168">"Menü öffnen"</string> + <!-- no translation found for expand_menu_text (3847736164494181168) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index 9c5e0c48f6cb..ea44bead6766 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Burbuja"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestionar"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Burbuja cerrada."</string> - <string name="restart_button_description" msgid="6712141648865547958">"Toca para reiniciar esta aplicación y verlo mejor."</string> + <string name="restart_button_description" msgid="6712141648865547958">"Toca para reiniciar esta aplicación y obtener una mejor vista."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"¿Problemas con la cámara?\nToca para reajustar"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"¿No se ha solucionado?\nToca para revertir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"¿No hay problemas con la cámara? Toca para cerrar."</string> diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml index fb23d11ef74a..90feff32cc2b 100644 --- a/libs/WindowManager/Shell/res/values-et/strings.xml +++ b/libs/WindowManager/Shell/res/values-et/strings.xml @@ -89,7 +89,7 @@ <string name="letterbox_education_got_it" msgid="4057634570866051177">"Selge"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Laiendage lisateabe saamiseks."</string> <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Kas taaskäivitada parema vaate saavutamiseks?"</string> - <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Saate rakenduse taaskäivitada, et see näeks ekraanikuval parem välja, kuid võite kaotada edenemise või salvestamata muudatused."</string> + <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Saate rakenduse taaskäivitada, et see näeks ekraanikuval parem välja, kuid võite kaotada edenemise või salvestamata muudatused"</string> <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Tühista"</string> <string name="letterbox_restart_restart" msgid="8529976234412442973">"Taaskäivita"</string> <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ära kuva uuesti"</string> diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index edff47a0be1a..13a2ea2db140 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -59,7 +59,7 @@ <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"خروج از «حالت یکدستی»"</string> <string name="bubbles_settings_button_description" msgid="1301286017420516912">"تنظیمات برای حبابکهای <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"سرریز"</string> - <string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"افزودن برگشتن به پشته"</string> + <string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"افزودن برگشت به پشته"</string> <string name="bubble_content_description_single" msgid="8495748092720065813">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> از <xliff:g id="APP_NAME">%2$s</xliff:g>"</string> <string name="bubble_content_description_stack" msgid="8071515017164630429">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> از <xliff:g id="APP_NAME">%2$s</xliff:g> و <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> مورد بیشتر"</string> <string name="bubble_accessibility_action_move_top_left" msgid="2644118920500782758">"انتقال به بالا سمت راست"</string> diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml index 6d19e55217f6..7814b7d38fed 100644 --- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Bulle"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Gérer"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulle ignorée."</string> - <string name="restart_button_description" msgid="6712141648865547958">"Pour obtenir un meilleur affichage, touchez pour redémarrer cette application."</string> + <string name="restart_button_description" msgid="6712141648865547958">"Touchez pour redémarrer cette application afin d\'obtenir un meilleur affichage."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo?\nTouchez pour réajuster"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu?\nTouchez pour rétablir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo? Touchez pour ignorer."</string> diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index 5fb91f7b6948..da5b5c9bfeba 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Bulle"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Gérer"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulle fermée."</string> - <string name="restart_button_description" msgid="6712141648865547958">"Pour un meilleur affichage, appuyez pour redémarrer cette appli."</string> + <string name="restart_button_description" msgid="6712141648865547958">"Appuyez pour redémarrer cette appli et avoir une meilleure vue."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo ?\nAppuyez pour réajuster"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu ?\nAppuyez pour rétablir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo ? Appuyez pour ignorer."</string> @@ -89,7 +89,7 @@ <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Développez pour obtenir plus d\'informations"</string> <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Redémarrer pour améliorer l\'affichage ?"</string> - <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Vous pouvez redémarrer l\'appli pour un meilleur rendu sur votre écran, mais il se peut que vous perdiez votre progression ou les modifications non enregistrées"</string> + <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Vous pouvez redémarrer l\'appli pour en améliorer son aspect sur votre écran, mais vous risquez de perdre votre progression ou les modifications non enregistrées"</string> <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Annuler"</string> <string name="letterbox_restart_restart" msgid="8529976234412442973">"Redémarrer"</string> <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ne plus afficher"</string> diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml index b0b0e9c6f5bc..fb5040b36a89 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings.xml @@ -89,7 +89,7 @@ <string name="letterbox_education_got_it" msgid="4057634570866051177">"ठीक है"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ज़्यादा जानकारी के लिए बड़ा करें."</string> <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"बेहतर व्यू पाने के लिए ऐप्लिकेशन को रीस्टार्ट करना है?"</string> - <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"स्क्रीन पर ऐप्लिकेशन का बेहतर व्यू पाने के लिए उसे रीस्टार्ट करें. हालांकि, इससे अब तक किया गया काम और सेव न किए गए बदलाव मिट सकते हैं"</string> + <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"स्क्रीन पर ऐप्लिकेशन का बेहतर व्यू पाने के लिए उसे रीस्टार्ट करें. हालांकि, आपने जो बदलाव सेव नहीं किए हैं या अब तक जो काम किए हैं उनका डेटा, ऐप्लिकेशन रीस्टार्ट करने पर मिट सकता है"</string> <string name="letterbox_restart_cancel" msgid="1342209132692537805">"रद्द करें"</string> <string name="letterbox_restart_restart" msgid="8529976234412442973">"रीस्टार्ट करें"</string> <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"फिर से न दिखाएं"</string> diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml index 08721f0e6746..2535657c7d86 100644 --- a/libs/WindowManager/Shell/res/values-hr/strings.xml +++ b/libs/WindowManager/Shell/res/values-hr/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Oblačić"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljanje"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblačić odbačen."</string> - <string name="restart_button_description" msgid="6712141648865547958">"Dodirnite za ponovno pokretanje te aplikacije i bolji prikaz."</string> + <string name="restart_button_description" msgid="6712141648865547958">"Dodirnite da biste ponovo pokrenuli tu aplikaciju kako biste bolje vidjeli."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi s fotoaparatom?\nDodirnite za popravak"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problem nije riješen?\nDodirnite za vraćanje"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemate problema s fotoaparatom? Dodirnite za odbacivanje."</string> diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index 3f6d9c551aa6..5747deb405ab 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -88,7 +88,7 @@ <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Ketuk dua kali di luar aplikasi untuk mengubah posisinya"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Oke"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Luaskan untuk melihat informasi selengkapnya."</string> - <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Mulai ulang untuk melihat tampilan yang lebih baik?"</string> + <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Mulai ulang untuk tampilan yang lebih baik?"</string> <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Anda dapat memulai ulang aplikasi agar terlihat lebih baik di layar, tetapi Anda mungkin kehilangan progres atau perubahan yang belum disimpan"</string> <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Batal"</string> <string name="letterbox_restart_restart" msgid="8529976234412442973">"Mulai ulang"</string> diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml index 20c16be3eaca..145d26d35b75 100644 --- a/libs/WindowManager/Shell/res/values-is/strings.xml +++ b/libs/WindowManager/Shell/res/values-is/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Blaðra"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Stjórna"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Blöðru lokað."</string> - <string name="restart_button_description" msgid="6712141648865547958">"Ýttu til að endurræsa forritið og fá betri sýn."</string> + <string name="restart_button_description" msgid="6712141648865547958">"Ýta til að endurræsa forritið og fá betri sýn."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Myndavélavesen?\nÝttu til að breyta stærð"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ennþá vesen?\nÝttu til að afturkalla"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ekkert myndavélavesen? Ýttu til að hunsa."</string> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index 191fbe85bd01..025646cbb9cd 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Fumetto"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestisci"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Fumetto ignorato."</string> - <string name="restart_button_description" msgid="6712141648865547958">"Tocca per riavviare l\'app e migliorare la visualizzazione"</string> + <string name="restart_button_description" msgid="6712141648865547958">"Tocca per riavviare quest\'app per una migliore visualizzazione."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi con la fotocamera?\nTocca per risolverli"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Il problema non si è risolto?\nTocca per ripristinare"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nessun problema con la fotocamera? Tocca per ignorare."</string> diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml index 8f2f6d8e882f..6c1bafee9d82 100644 --- a/libs/WindowManager/Shell/res/values-ja/strings.xml +++ b/libs/WindowManager/Shell/res/values-ja/strings.xml @@ -54,7 +54,7 @@ <string name="accessibility_split_top" msgid="2789329702027147146">"上に分割"</string> <string name="accessibility_split_bottom" msgid="8694551025220868191">"下に分割"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"片手モードの使用"</string> - <string name="one_handed_tutorial_description" msgid="3486582858591353067">"終了するには、画面を下から上にスワイプするか、アプリの上側の任意の場所をタップします"</string> + <string name="one_handed_tutorial_description" msgid="3486582858591353067">"終了するには、画面を下から上にスワイプするか、アプリの任意の場所をタップします"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"片手モードを開始します"</string> <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"片手モードを終了します"</string> <string name="bubbles_settings_button_description" msgid="1301286017420516912">"<xliff:g id="APP_NAME">%1$s</xliff:g> のバブルの設定"</string> @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"バブル"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ふきだしが非表示になっています。"</string> - <string name="restart_button_description" msgid="6712141648865547958">"タップしてこのアプリを再起動すると、より見やすく表示されます。"</string> + <string name="restart_button_description" msgid="6712141648865547958">"タップしてこのアプリを再起動すると、表示が適切になります。"</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"カメラに関する問題の場合は、\nタップすると修正できます"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"修正されなかった場合は、\nタップすると元に戻ります"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"カメラに関する問題でない場合は、タップすると閉じます。"</string> diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml index c40cd2fb24aa..7c9120e22b30 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Көпіршік"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Басқару"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Қалқыма хабар жабылды."</string> - <string name="restart_button_description" msgid="6712141648865547958">"Түртсеңіз, қолданба жабылып, ыңғайлы көрініспен қайта ашылады."</string> + <string name="restart_button_description" msgid="6712141648865547958">"Ыңғайлы көріністі реттеу үшін қолданбаны түртіп, өшіріп қосыңыз."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерада қателер шықты ма?\nЖөндеу үшін түртіңіз."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Жөнделмеді ме?\nҚайтару үшін түртіңіз."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерада қателер шықпады ма? Жабу үшін түртіңіз."</string> diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml index 55697ca23a86..39d717dd461a 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"버블"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"관리"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"대화창을 닫았습니다."</string> - <string name="restart_button_description" msgid="6712141648865547958">"더 편하게 보기를 원하면 탭하여 앱을 다시 시작하세요."</string> + <string name="restart_button_description" msgid="6712141648865547958">"보기를 개선하려면 탭하여 앱을 다시 시작합니다."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"카메라 문제가 있나요?\n해결하려면 탭하세요."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"해결되지 않았나요?\n되돌리려면 탭하세요."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"카메라에 문제가 없나요? 닫으려면 탭하세요."</string> diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml index 19df267e1d27..f210ea29da00 100644 --- a/libs/WindowManager/Shell/res/values-ky/strings.xml +++ b/libs/WindowManager/Shell/res/values-ky/strings.xml @@ -24,7 +24,7 @@ <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string> <string name="pip_menu_accessibility_title" msgid="8129016817688656249">"Сүрөт ичиндеги сүрөт менюсу"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> – сүрөт ичиндеги сүрөт"</string> - <string name="pip_notification_message" msgid="8854051911700302620">"Эгер <xliff:g id="NAME">%s</xliff:g> колдонмосу бул функцияны пайдаланбасын десеңиз, параметрлерди ачып туруп, аны өчүрүп коюңуз."</string> + <string name="pip_notification_message" msgid="8854051911700302620">"Эгер <xliff:g id="NAME">%s</xliff:g> колдонмосу бул функцияны пайдаланбасын десеңиз, жөндөөлөрдү ачып туруп, аны өчүрүп коюңуз."</string> <string name="pip_play" msgid="3496151081459417097">"Ойнотуу"</string> <string name="pip_pause" msgid="690688849510295232">"Тындыруу"</string> <string name="pip_skip_to_next" msgid="8403429188794867653">"Кийинкисине өткөрүп жиберүү"</string> diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml index 1567d61d833f..427433c7f2d4 100644 --- a/libs/WindowManager/Shell/res/values-mk/strings.xml +++ b/libs/WindowManager/Shell/res/values-mk/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Балонче"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Управувајте"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Балончето е отфрлено."</string> - <string name="restart_button_description" msgid="6712141648865547958">"За подобар приказ, допрете за да ја рестартирате апликацијава."</string> + <string name="restart_button_description" msgid="6712141648865547958">"Допрете за да ја рестартирате апликацијава за подобар приказ."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблеми со камерата?\nДопрете за да се совпадне повторно"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не се поправи?\nДопрете за враќање"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нема проблеми со камерата? Допрете за отфрлање."</string> diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml index 267b8a38a6d7..e4c70537c452 100644 --- a/libs/WindowManager/Shell/res/values-or/strings.xml +++ b/libs/WindowManager/Shell/res/values-or/strings.xml @@ -26,7 +26,7 @@ <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> \"ଛବି-ଭିତରେ-ଛବି\"ରେ ଅଛି"</string> <string name="pip_notification_message" msgid="8854051911700302620">"ଏହି ବୈଶିଷ୍ଟ୍ୟ <xliff:g id="NAME">%s</xliff:g> ବ୍ୟବହାର ନକରିବାକୁ ଯଦି ଆପଣ ଚାହାଁନ୍ତି, ସେଟିଙ୍ଗ ଖୋଲିବାକୁ ଟାପ୍ କରନ୍ତୁ ଏବଂ ଏହା ଅଫ୍ କରିଦିଅନ୍ତୁ।"</string> <string name="pip_play" msgid="3496151081459417097">"ପ୍ଲେ କରନ୍ତୁ"</string> - <string name="pip_pause" msgid="690688849510295232">"ବିରତ କରନ୍ତୁ"</string> + <string name="pip_pause" msgid="690688849510295232">"ପଜ୍ କରନ୍ତୁ"</string> <string name="pip_skip_to_next" msgid="8403429188794867653">"ପରବର୍ତ୍ତୀକୁ ଯାଆନ୍ତୁ"</string> <string name="pip_skip_to_prev" msgid="7172158111196394092">"ପୂର୍ବବର୍ତ୍ତୀକୁ ଛାଡ଼ନ୍ତୁ"</string> <string name="accessibility_action_pip_resize" msgid="4623966104749543182">"ରିସାଇଜ୍ କରନ୍ତୁ"</string> diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml index a3d6ce5a4c5a..ed0cdb61dacf 100644 --- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml @@ -24,7 +24,7 @@ <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_menu_accessibility_title" msgid="8129016817688656249">"Menu de ecrã no ecrã"</string> <string name="pip_notification_title" msgid="1347104727641353453">"A app <xliff:g id="NAME">%s</xliff:g> está no modo de ecrã no ecrã"</string> - <string name="pip_notification_message" msgid="8854051911700302620">"Se não quer que a app <xliff:g id="NAME">%s</xliff:g> utilize esta funcionalidade, toque para abrir as definições e desative-a."</string> + <string name="pip_notification_message" msgid="8854051911700302620">"Se não pretende que a app <xliff:g id="NAME">%s</xliff:g> utilize esta funcionalidade, toque para abrir as definições e desative-a."</string> <string name="pip_play" msgid="3496151081459417097">"Reproduzir"</string> <string name="pip_pause" msgid="690688849510295232">"Pausar"</string> <string name="pip_skip_to_next" msgid="8403429188794867653">"Mudar para o seguinte"</string> @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Balão"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Gerir"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balão ignorado."</string> - <string name="restart_button_description" msgid="6712141648865547958">"Toque para reiniciar esta app e ver melhor."</string> + <string name="restart_button_description" msgid="6712141648865547958">"Toque para reiniciar esta app e ficar com uma melhor visão."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmara?\nToque aqui para reajustar"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Não foi corrigido?\nToque para reverter"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nenhum problema com a câmara? Toque para ignorar."</string> diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml index 58ad60a87982..8a64b1686543 100644 --- a/libs/WindowManager/Shell/res/values-ro/strings.xml +++ b/libs/WindowManager/Shell/res/values-ro/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Balon"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestionează"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balonul a fost respins."</string> - <string name="restart_button_description" msgid="6712141648865547958">"Atinge ca să repornești aplicația pentru o afișare mai bună."</string> + <string name="restart_button_description" msgid="6712141648865547958">"Atinge ca să repornești aplicația pentru o vizualizare mai bună."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Ai probleme cu camera foto?\nAtinge pentru a reîncadra"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nu ai remediat problema?\nAtinge pentru a reveni"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nu ai probleme cu camera foto? Atinge pentru a închide."</string> diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml index 85798cf9f784..307efc9d6a2e 100644 --- a/libs/WindowManager/Shell/res/values-sr/strings.xml +++ b/libs/WindowManager/Shell/res/values-sr/strings.xml @@ -89,7 +89,7 @@ <string name="letterbox_education_got_it" msgid="4057634570866051177">"Важи"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Проширите за још информација."</string> <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Желите ли да рестартујете ради бољег приказа?"</string> - <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Можете да рестартујете апликацију да би изгледала боље на екрану, али можете да изгубите напредак или несачуване промене"</string> + <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Можете да рестартујете апликацију да би изгледала боље на екрану, с тим што можете да изгубите оно што сте урадили или несачуване промене, ако их има"</string> <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Откажи"</string> <string name="letterbox_restart_restart" msgid="8529976234412442973">"Рестартуј"</string> <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Не приказуј поново"</string> diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml index 5bb4c27ed6c7..fd5f0e646d9b 100644 --- a/libs/WindowManager/Shell/res/values-ta/strings.xml +++ b/libs/WindowManager/Shell/res/values-ta/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"பபிள்"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"நிர்வகி"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"குமிழ் நிராகரிக்கப்பட்டது."</string> - <string name="restart_button_description" msgid="6712141648865547958">"இங்கு தட்டி ஆப்ஸை மீண்டும் தொடங்கி, ஆப்ஸ் காட்சியை இன்னும் சிறப்பாக்கலாம்."</string> + <string name="restart_button_description" msgid="6712141648865547958">"இங்கு தட்டுவதன் மூலம் இந்த ஆப்ஸை மீண்டும் தொடங்கி, ஆப்ஸ் காட்டப்படும் விதத்தை இன்னும் சிறப்பாக்கலாம்."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"கேமரா தொடர்பான சிக்கல்களா?\nமீண்டும் பொருத்த தட்டவும்"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"சிக்கல்கள் சரிசெய்யப்படவில்லையா?\nமாற்றியமைக்க தட்டவும்"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"கேமரா தொடர்பான சிக்கல்கள் எதுவும் இல்லையா? நிராகரிக்க தட்டவும்."</string> diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml index 0281c1c8c396..7d974005dd31 100644 --- a/libs/WindowManager/Shell/res/values-vi/strings.xml +++ b/libs/WindowManager/Shell/res/values-vi/strings.xml @@ -79,7 +79,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Bong bóng"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Quản lý"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Đã đóng bong bóng."</string> - <string name="restart_button_description" msgid="6712141648865547958">"Nhấn để khởi động lại ứng dụng để có trải nghiệm xem tốt hơn."</string> + <string name="restart_button_description" msgid="6712141648865547958">"Nhấn để khởi động lại ứng dụng này để xem tốt hơn."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Có vấn đề với máy ảnh?\nHãy nhấn để sửa lỗi"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Bạn chưa khắc phục vấn đề?\nHãy nhấn để hủy bỏ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Không có vấn đề với máy ảnh? Hãy nhấn để đóng."</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml index 3d33ecaccc38..6f399e51be4d 100644 --- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml @@ -24,7 +24,7 @@ <string name="pip_menu_title" msgid="5393619322111827096">"選單"</string> <string name="pip_menu_accessibility_title" msgid="8129016817688656249">"畫中畫選單"</string> <string name="pip_notification_title" msgid="1347104727641353453">"「<xliff:g id="NAME">%s</xliff:g>」目前在畫中畫模式"</string> - <string name="pip_notification_message" msgid="8854051911700302620">"如果你不想「<xliff:g id="NAME">%s</xliff:g>」使用此功能,請輕按以開啟設定,然後停用此功能。"</string> + <string name="pip_notification_message" msgid="8854051911700302620">"如果您不想「<xliff:g id="NAME">%s</xliff:g>」使用此功能,請輕按以開啟設定,然後停用此功能。"</string> <string name="pip_play" msgid="3496151081459417097">"播放"</string> <string name="pip_pause" msgid="690688849510295232">"暫停"</string> <string name="pip_skip_to_next" msgid="8403429188794867653">"跳到下一個"</string> @@ -88,8 +88,8 @@ <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"在應用程式外輕按兩下即可調整位置"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"知道了"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展開即可查看詳情。"</string> - <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"要重新啟動以改善檢視畫面嗎?"</string> - <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"你可重新啟動應用程式,讓系統更新檢視畫面;但系統可能不會儲存目前進度及你作出的任何變更"</string> + <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"要重新啟動改善檢視畫面嗎?"</string> + <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"您可重新啟動應用程式,讓系統更新檢視畫面;但系統可能不會儲存目前進度及您作出的任何變更"</string> <string name="letterbox_restart_cancel" msgid="1342209132692537805">"取消"</string> <string name="letterbox_restart_restart" msgid="8529976234412442973">"重新啟動"</string> <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"不要再顯示"</string> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index b14c3c10846b..08da4857a0b0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -1927,6 +1927,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, pw.println(innerPrefix + "mLeash=" + mLeash); pw.println(innerPrefix + "mState=" + mPipTransitionState.getTransitionState()); pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams); + mPipTransitionController.dump(pw, innerPrefix); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java index b8407c465741..e3d53fc415db 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java @@ -72,6 +72,7 @@ import com.android.wm.shell.transition.CounterRotatorHelper; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.util.TransitionUtil; +import java.io.PrintWriter; import java.util.Optional; /** @@ -339,19 +340,36 @@ public class PipTransition extends PipTransitionController { } // This means an expand happened before enter-pip finished and we are now "merging" a // no-op transition that happens to match our exit-pip. + // Or that the keyguard is up and preventing the transition from applying, in which case we + // want to manually reset pip. (b/283783868) boolean cancelled = false; if (mPipAnimationController.getCurrentAnimator() != null) { mPipAnimationController.getCurrentAnimator().cancel(); + mPipAnimationController.resetAnimatorState(); cancelled = true; } + // Unset exitTransition AFTER cancel so that finishResize knows we are merging. mExitTransition = null; - if (!cancelled || aborted) return; + if (!cancelled) return; final ActivityManager.RunningTaskInfo taskInfo = mPipOrganizer.getTaskInfo(); if (taskInfo != null) { - startExpandAnimation(taskInfo, mPipOrganizer.getSurfaceControl(), - mPipBoundsState.getBounds(), mPipBoundsState.getBounds(), - new Rect(mExitDestinationBounds), Surface.ROTATION_0, null /* startT */); + if (aborted) { + // keyguard case - the transition got aborted, so we want to reset state and + // windowing mode before reapplying the resize transaction + sendOnPipTransitionFinished(TRANSITION_DIRECTION_LEAVE_PIP); + mPipOrganizer.onExitPipFinished(taskInfo); + + WindowContainerTransaction wct = new WindowContainerTransaction(); + mPipOrganizer.applyWindowingModeChangeOnExit(wct, TRANSITION_DIRECTION_LEAVE_PIP); + wct.setBounds(taskInfo.token, null); + mPipOrganizer.applyFinishBoundsResize(wct, TRANSITION_DIRECTION_LEAVE_PIP, false); + } else { + // merge case + startExpandAnimation(taskInfo, mPipOrganizer.getSurfaceControl(), + mPipBoundsState.getBounds(), mPipBoundsState.getBounds(), + new Rect(mExitDestinationBounds), Surface.ROTATION_0, null /* startT */); + } } mExitDestinationBounds.setEmpty(); mCurrentPipTaskToken = null; @@ -434,6 +452,9 @@ public class PipTransition extends PipTransitionController { @Override public void forceFinishTransition() { + // mFinishCallback might be null with an outdated mCurrentPipTaskToken + // for example, when app crashes while in PiP and exit transition has not started + mCurrentPipTaskToken = null; if (mFinishCallback == null) return; mFinishCallback.onTransitionFinished(null /* wct */, null /* callback */); mFinishCallback = null; @@ -567,7 +588,16 @@ public class PipTransition extends PipTransitionController { mPipBoundsState.getDisplayBounds()); mFinishCallback = (wct, wctCB) -> { mPipOrganizer.onExitPipFinished(taskInfo); - if (!Transitions.SHELL_TRANSITIONS_ROTATION && toFullscreen) { + + // TODO(b/286346098): remove the OPEN app flicker completely + // not checking if we go to fullscreen helps avoid getting pip into an inconsistent + // state after the flicker occurs. This is a temp solution until flicker is removed. + if (!Transitions.SHELL_TRANSITIONS_ROTATION) { + // will help to debug the case when we are not exiting to fullscreen + if (!toFullscreen) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: startExitAnimation() not exiting to fullscreen", TAG); + } wct = wct != null ? wct : new WindowContainerTransaction(); wct.setBounds(pipTaskToken, null); mPipOrganizer.applyWindowingModeChangeOnExit(wct, TRANSITION_DIRECTION_LEAVE_PIP); @@ -831,7 +861,7 @@ public class PipTransition extends PipTransitionController { } final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); - final Rect currentBounds = taskInfo.configuration.windowConfiguration.getBounds(); + final Rect currentBounds = pipChange.getStartAbsBounds(); int rotationDelta = deltaRotation(startRotation, endRotation); Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect( taskInfo.pictureInPictureParams, currentBounds, destinationBounds); @@ -856,6 +886,9 @@ public class PipTransition extends PipTransitionController { final int enterAnimationType = mEnterAnimationType; if (enterAnimationType == ANIM_TYPE_ALPHA) { startTransaction.setAlpha(leash, 0f); + } else { + // set alpha to 1, because for multi-activity PiP it will create a new task with alpha 0 + startTransaction.setAlpha(leash, 1f); } startTransaction.apply(); @@ -1047,7 +1080,7 @@ public class PipTransition extends PipTransitionController { // When the PIP window is visible and being a part of the transition, such as display // rotation, we need to update its bounds and rounded corner. final SurfaceControl leash = pipChange.getLeash(); - final Rect destBounds = mPipBoundsState.getBounds(); + final Rect destBounds = mPipOrganizer.getCurrentOrAnimatingBounds(); final boolean isInPip = mPipTransitionState.isInPip(); mSurfaceTransactionHelper .crop(startTransaction, leash, destBounds) @@ -1108,4 +1141,12 @@ public class PipTransition extends PipTransitionController { PipMenuController.ALPHA_NO_CHANGE); mPipMenuController.updateMenuBounds(destinationBounds); } + + @Override + public void dump(PrintWriter pw, String prefix) { + final String innerPrefix = prefix + " "; + pw.println(prefix + TAG); + pw.println(innerPrefix + "mCurrentPipTaskToken=" + mCurrentPipTaskToken); + pw.println(innerPrefix + "mFinishCallback=" + mFinishCallback); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java index e1bcd70c256b..63627938ec87 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java @@ -42,6 +42,7 @@ import com.android.wm.shell.common.split.SplitScreenUtils; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; @@ -283,4 +284,9 @@ public abstract class PipTransitionController implements Transitions.TransitionH */ void onPipTransitionCanceled(int direction); } + + /** + * Dumps internal states. + */ + public void dump(PrintWriter pw, String prefix) {} } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 01d8967c7d60..7699e2f7c13d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -2441,6 +2441,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitLayout.setFreezeDividerWindow(false); final StageChangeRecord record = new StageChangeRecord(); + final int transitType = info.getType(); + boolean hasEnteringPip = false; for (int iC = 0; iC < info.getChanges().size(); ++iC) { final TransitionInfo.Change change = info.getChanges().get(iC); if (change.getMode() == TRANSIT_CHANGE @@ -2448,6 +2450,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitLayout.update(startTransaction); } + if (mMixedHandler.isEnteringPip(change, transitType)) { + hasEnteringPip = true; + } + final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); if (taskInfo == null) continue; if (taskInfo.token.equals(mRootTaskInfo.token)) { @@ -2496,6 +2502,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } } + + if (hasEnteringPip) { + mMixedHandler.animatePendingEnterPipFromSplit(transition, info, + startTransaction, finishTransaction, finishCallback); + return true; + } + final ArraySet<StageTaskListener> dismissStages = record.getShouldDismissedStage(); if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0 || dismissStages.size() == 1) { @@ -2530,8 +2543,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // handling to the mixed-handler to deal with splitting it up. if (mMixedHandler.animatePendingSplitWithDisplayChange(transition, info, startTransaction, finishTransaction, finishCallback)) { - mSplitLayout.update(startTransaction); - startTransaction.apply(); + if (mSplitTransitions.isPendingResize(transition)) { + // Only need to update in resize because divider exist before transition. + mSplitLayout.update(startTransaction); + startTransaction.apply(); + } return true; } } @@ -2828,18 +2844,24 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } + final ArrayMap<Integer, SurfaceControl> dismissingTasks = new ArrayMap<>(); + for (int i = info.getChanges().size() - 1; i >= 0; --i) { + final TransitionInfo.Change change = info.getChanges().get(i); + final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); + if (taskInfo == null) continue; + if (getStageOfTask(taskInfo) != null + || getSplitItemPosition(change.getLastParent()) != SPLIT_POSITION_UNDEFINED) { + dismissingTasks.put(taskInfo.taskId, change.getLeash()); + } + } + + if (shouldBreakPairedTaskInRecents(dismissReason)) { // Notify recents if we are exiting in a way that breaks the pair, and disable further // updates to splits in the recents until we enter split again mRecentTasks.ifPresent(recentTasks -> { - for (int i = info.getChanges().size() - 1; i >= 0; --i) { - final TransitionInfo.Change change = info.getChanges().get(i); - final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); - if (taskInfo != null && (getStageOfTask(taskInfo) != null - || getSplitItemPosition(change.getLastParent()) - != SPLIT_POSITION_UNDEFINED)) { - recentTasks.removeSplitPair(taskInfo.taskId); - } + for (int i = dismissingTasks.keySet().size() - 1; i >= 0; --i) { + recentTasks.removeSplitPair(dismissingTasks.keyAt(i)); } }); } @@ -2857,6 +2879,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, t.hide(toStage == STAGE_TYPE_MAIN ? mSideStage.mRootLeash : mMainStage.mRootLeash); t.setPosition(toStage == STAGE_TYPE_MAIN ? mMainStage.mRootLeash : mSideStage.mRootLeash, 0, 0); + } else { + for (int i = dismissingTasks.keySet().size() - 1; i >= 0; --i) { + finishT.hide(dismissingTasks.valueAt(i)); + } } if (toStage == STAGE_TYPE_UNDEFINED) { @@ -2866,7 +2892,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } // Hide divider and dim layer on transition finished. - setDividerVisibility(false, finishT); + setDividerVisibility(false, t); finishT.hide(mMainStage.mDimLayer); finishT.hide(mSideStage.mDimLayer); } @@ -2890,8 +2916,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSideStage.getSplitDecorManager().release(callbackT); callbackWct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token, false); }); - - addDividerBarToTransition(info, false /* show */); return true; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java index c964df1452e0..c2f15f6cba75 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java @@ -16,6 +16,7 @@ package com.android.wm.shell.startingsurface; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.graphics.Color.WHITE; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; @@ -77,6 +78,13 @@ public class TaskSnapshotWindow { @NonNull Runnable clearWindowHandler) { final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo; final int taskId = runningTaskInfo.taskId; + + // if we're in PIP we don't want to create the snapshot + if (runningTaskInfo.getWindowingMode() == WINDOWING_MODE_PINNED) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW, + "did not create taskSnapshot due to being in PIP"); + return null; + } ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW, "create taskSnapshot surface for task: %d", taskId); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java index e83780a6fc77..d0a361a8ecd2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -25,6 +25,7 @@ import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; +import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP; import static com.android.wm.shell.util.TransitionUtil.isOpeningType; @@ -447,7 +448,8 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, } finishCallback.onTransitionFinished(mixed.mFinishWCT, wctCB); }; - if (isGoingHome) { + if (isGoingHome || mSplitHandler.getSplitItemPosition(pipChange.getLastParent()) + != SPLIT_POSITION_UNDEFINED) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animation is actually mixed " + "since entering-PiP caused us to leave split and return home."); // We need to split the transition into 2 parts: the pip part (animated by pip) @@ -476,6 +478,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, } } + mPipHandler.setEnterAnimationType(ANIM_TYPE_ALPHA); mPipHandler.startEnterAnimation(pipChange, startTransaction, finishTransaction, finishCB); // Dispatch the rest of the transition normally. This will most-likely be taken by @@ -516,10 +519,27 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, } /** + * This is intended to be called by SplitCoordinator as a helper to mix a split handling + * transition with an entering-pip change. The use-case for this is when an auto-pip change + * gets collected into the transition which has already claimed by + * StageCoordinator.handleRequest. This happens when launching a fullscreen app while having an + * auto-pip activity in the foreground split pair. + */ + // TODO(b/287704263): Remove when split/mixed are reversed. + public boolean animatePendingEnterPipFromSplit(IBinder transition, TransitionInfo info, + SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT, + Transitions.TransitionFinishCallback finishCallback) { + final MixedTransition mixed = new MixedTransition( + MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT, transition); + mActiveTransitions.add(mixed); + return animateEnterPipFromSplit(mixed, info, startT, finishT, finishCallback); + } + + /** * This is intended to be called by SplitCoordinator as a helper to mix an already-pending * split transition with a display-change. The use-case for this is when a display * change/rotation gets collected into a split-screen enter/exit transition which has already - * been claimed by StageCoordinator.handleRequest . This happens during launcher tests. + * been claimed by StageCoordinator.handleRequest. This happens during launcher tests. */ public boolean animatePendingSplitWithDisplayChange(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startT, @@ -657,6 +677,13 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, return mPipHandler.requestHasPipEnter(request); } + /** Whether a particular change is a window that is entering pip. */ + // TODO(b/287704263): Remove when split/mixed are reversed. + public boolean isEnteringPip(TransitionInfo.Change change, + @WindowManager.TransitionType int transitType) { + return mPipHandler.isEnteringPip(change, transitType); + } + @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java index 3b05651f884b..44c76de945b0 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java @@ -75,6 +75,7 @@ import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.split.SplitDecorManager; import com.android.wm.shell.common.split.SplitLayout; +import com.android.wm.shell.transition.DefaultMixedHandler; import com.android.wm.shell.transition.Transitions; import org.junit.Before; @@ -101,6 +102,7 @@ public class SplitTransitionTests extends ShellTestCase { @Mock private SurfaceSession mSurfaceSession; @Mock private IconProvider mIconProvider; @Mock private ShellExecutor mMainExecutor; + @Mock private DefaultMixedHandler mMixedHandler; private SplitLayout mSplitLayout; private MainStage mMainStage; private SideStage mSideStage; @@ -131,6 +133,7 @@ public class SplitTransitionTests extends ShellTestCase { mSyncQueue, mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController, mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool, mMainExecutor, Optional.empty()); + mStageCoordinator.setMixedHandler(mMixedHandler); mSplitScreenTransitions = mStageCoordinator.getSplitTransitions(); doAnswer((Answer<IBinder>) invocation -> mock(IBinder.class)) .when(mTransitions).startTransition(anyInt(), any(), any()); diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp index 15aaae25f754..f0c639574a9f 100644 --- a/libs/androidfw/ApkAssets.cpp +++ b/libs/androidfw/ApkAssets.cpp @@ -27,39 +27,34 @@ using base::unique_fd; constexpr const char* kResourcesArsc = "resources.arsc"; -ApkAssets::ApkAssets(std::unique_ptr<Asset> resources_asset, +ApkAssets::ApkAssets(PrivateConstructorUtil, std::unique_ptr<Asset> resources_asset, std::unique_ptr<LoadedArsc> loaded_arsc, - std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap) + std::unique_ptr<AssetsProvider> assets, package_property_t property_flags, + std::unique_ptr<Asset> idmap_asset, std::unique_ptr<LoadedIdmap> loaded_idmap) : resources_asset_(std::move(resources_asset)), loaded_arsc_(std::move(loaded_arsc)), assets_provider_(std::move(assets)), property_flags_(property_flags), idmap_asset_(std::move(idmap_asset)), - loaded_idmap_(std::move(loaded_idmap)) {} + loaded_idmap_(std::move(loaded_idmap)) { +} -std::unique_ptr<ApkAssets> ApkAssets::Load(const std::string& path, package_property_t flags) { +ApkAssetsPtr ApkAssets::Load(const std::string& path, package_property_t flags) { return Load(ZipAssetsProvider::Create(path, flags), flags); } -std::unique_ptr<ApkAssets> ApkAssets::LoadFromFd(base::unique_fd fd, - const std::string& debug_name, - package_property_t flags, - off64_t offset, - off64_t len) { +ApkAssetsPtr ApkAssets::LoadFromFd(base::unique_fd fd, const std::string& debug_name, + package_property_t flags, off64_t offset, off64_t len) { return Load(ZipAssetsProvider::Create(std::move(fd), debug_name, offset, len), flags); } -std::unique_ptr<ApkAssets> ApkAssets::Load(std::unique_ptr<AssetsProvider> assets, - package_property_t flags) { +ApkAssetsPtr ApkAssets::Load(std::unique_ptr<AssetsProvider> assets, package_property_t flags) { return LoadImpl(std::move(assets), flags, nullptr /* idmap_asset */, nullptr /* loaded_idmap */); } -std::unique_ptr<ApkAssets> ApkAssets::LoadTable(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<AssetsProvider> assets, - package_property_t flags) { +ApkAssetsPtr ApkAssets::LoadTable(std::unique_ptr<Asset> resources_asset, + std::unique_ptr<AssetsProvider> assets, + package_property_t flags) { if (resources_asset == nullptr) { return {}; } @@ -67,8 +62,7 @@ std::unique_ptr<ApkAssets> ApkAssets::LoadTable(std::unique_ptr<Asset> resources nullptr /* loaded_idmap */); } -std::unique_ptr<ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path, - package_property_t flags) { +ApkAssetsPtr ApkAssets::LoadOverlay(const std::string& idmap_path, package_property_t flags) { CHECK((flags & PROPERTY_LOADER) == 0U) << "Cannot load RROs through loaders"; auto idmap_asset = AssetsProvider::CreateAssetFromFile(idmap_path); if (idmap_asset == nullptr) { @@ -103,10 +97,10 @@ std::unique_ptr<ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path, std::move(loaded_idmap)); } -std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap) { +ApkAssetsPtr ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider> assets, + package_property_t property_flags, + std::unique_ptr<Asset> idmap_asset, + std::unique_ptr<LoadedIdmap> loaded_idmap) { if (assets == nullptr) { return {}; } @@ -125,11 +119,11 @@ std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider> a std::move(idmap_asset), std::move(loaded_idmap)); } -std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap) { +ApkAssetsPtr ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_asset, + std::unique_ptr<AssetsProvider> assets, + package_property_t property_flags, + std::unique_ptr<Asset> idmap_asset, + std::unique_ptr<LoadedIdmap> loaded_idmap) { if (assets == nullptr ) { return {}; } @@ -155,10 +149,9 @@ std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_ return {}; } - return std::unique_ptr<ApkAssets>(new ApkAssets(std::move(resources_asset), - std::move(loaded_arsc), std::move(assets), - property_flags, std::move(idmap_asset), - std::move(loaded_idmap))); + return ApkAssetsPtr::make(PrivateConstructorUtil{}, std::move(resources_asset), + std::move(loaded_arsc), std::move(assets), property_flags, + std::move(idmap_asset), std::move(loaded_idmap)); } std::optional<std::string_view> ApkAssets::GetPath() const { @@ -174,4 +167,5 @@ bool ApkAssets::IsUpToDate() const { return IsLoader() || ((!loaded_idmap_ || loaded_idmap_->IsUpToDate()) && assets_provider_->IsUpToDate()); } + } // namespace android diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index 55cd3d62f006..bff197cc290f 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -91,13 +91,14 @@ struct FindEntryResult { StringPoolRef entry_string_ref; }; -AssetManager2::AssetManager2() { - memset(&configuration_, 0, sizeof(configuration_)); +AssetManager2::AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration) + : configuration_(configuration) { + // Don't invalidate caches here as there's nothing cached yet. + SetApkAssets(apk_assets, false); } -bool AssetManager2::SetApkAssets(std::vector<const ApkAssets*> apk_assets, bool invalidate_caches) { - apk_assets_ = std::move(apk_assets); - BuildDynamicRefTable(); +bool AssetManager2::SetApkAssets(ApkAssetsList apk_assets, bool invalidate_caches) { + BuildDynamicRefTable(apk_assets); RebuildFilterList(); if (invalidate_caches) { InvalidateCaches(static_cast<uint32_t>(-1)); @@ -105,7 +106,21 @@ bool AssetManager2::SetApkAssets(std::vector<const ApkAssets*> apk_assets, bool return true; } -void AssetManager2::BuildDynamicRefTable() { +bool AssetManager2::SetApkAssets(std::initializer_list<ApkAssetsPtr> apk_assets, + bool invalidate_caches) { + return SetApkAssets(ApkAssetsList(apk_assets.begin(), apk_assets.size()), invalidate_caches); +} + +void AssetManager2::BuildDynamicRefTable(ApkAssetsList apk_assets) { + auto op = StartOperation(); + + apk_assets_.resize(apk_assets.size()); + for (size_t i = 0; i != apk_assets.size(); ++i) { + apk_assets_[i].first = apk_assets[i]; + // Let's populate the locked assets right away as we're going to need them here later. + apk_assets_[i].second = apk_assets[i]; + } + package_groups_.clear(); package_ids_.fill(0xff); @@ -116,16 +131,19 @@ void AssetManager2::BuildDynamicRefTable() { // Overlay resources are not directly referenced by an application so their resource ids // can change throughout the application's lifetime. Assign overlay package ids last. - std::vector<const ApkAssets*> sorted_apk_assets(apk_assets_); - std::stable_partition(sorted_apk_assets.begin(), sorted_apk_assets.end(), [](const ApkAssets* a) { - return !a->IsOverlay(); - }); + std::vector<const ApkAssets*> sorted_apk_assets; + sorted_apk_assets.reserve(apk_assets.size()); + for (auto& asset : apk_assets) { + sorted_apk_assets.push_back(asset.get()); + } + std::stable_partition(sorted_apk_assets.begin(), sorted_apk_assets.end(), + [](auto a) { return !a->IsOverlay(); }); // The assets cookie must map to the position of the apk assets in the unsorted apk assets list. std::unordered_map<const ApkAssets*, ApkAssetsCookie> apk_assets_cookies; - apk_assets_cookies.reserve(apk_assets_.size()); - for (size_t i = 0, n = apk_assets_.size(); i < n; i++) { - apk_assets_cookies[apk_assets_[i]] = static_cast<ApkAssetsCookie>(i); + apk_assets_cookies.reserve(apk_assets.size()); + for (size_t i = 0, n = apk_assets.size(); i < n; i++) { + apk_assets_cookies[apk_assets[i].get()] = static_cast<ApkAssetsCookie>(i); } // 0x01 is reserved for the android package. @@ -240,9 +258,11 @@ void AssetManager2::BuildDynamicRefTable() { void AssetManager2::DumpToLog() const { LOG(INFO) << base::StringPrintf("AssetManager2(this=%p)", this); + auto op = StartOperation(); std::string list; - for (const auto& apk_assets : apk_assets_) { - base::StringAppendF(&list, "%s,", apk_assets->GetDebugName().c_str()); + for (size_t i = 0; i < apk_assets_.size(); ++i) { + const auto& assets = GetApkAssets(i); + base::StringAppendF(&list, "%s,", assets ? assets->GetDebugName().c_str() : "nullptr"); } LOG(INFO) << "ApkAssets: " << list; @@ -279,7 +299,9 @@ const ResStringPool* AssetManager2::GetStringPoolForCookie(ApkAssetsCookie cooki if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) { return nullptr; } - return apk_assets_[cookie]->GetLoadedArsc()->GetStringPool(); + auto op = StartOperation(); + const auto& assets = GetApkAssets(cookie); + return assets ? assets->GetLoadedArsc()->GetStringPool() : nullptr; } const DynamicRefTable* AssetManager2::GetDynamicRefTableForPackage(uint32_t package_id) const { @@ -329,9 +351,14 @@ const std::unordered_map<std::string, std::string>* bool AssetManager2::GetOverlayablesToString(android::StringPiece package_name, std::string* out) const { + auto op = StartOperation(); uint8_t package_id = 0U; - for (const auto& apk_assets : apk_assets_) { - const LoadedArsc* loaded_arsc = apk_assets->GetLoadedArsc(); + for (size_t i = 0; i != apk_assets_.size(); ++i) { + const auto& assets = GetApkAssets(i); + if (!assets) { + continue; + } + const LoadedArsc* loaded_arsc = assets->GetLoadedArsc(); if (loaded_arsc == nullptr) { continue; } @@ -384,8 +411,14 @@ bool AssetManager2::GetOverlayablesToString(android::StringPiece package_name, } bool AssetManager2::ContainsAllocatedTable() const { - return std::find_if(apk_assets_.begin(), apk_assets_.end(), - std::mem_fn(&ApkAssets::IsTableAllocated)) != apk_assets_.end(); + auto op = StartOperation(); + for (size_t i = 0; i != apk_assets_.size(); ++i) { + const auto& assets = GetApkAssets(i); + if (assets && assets->IsTableAllocated()) { + return true; + } + } + return false; } void AssetManager2::SetConfiguration(const ResTable_config& configuration) { @@ -398,8 +431,8 @@ void AssetManager2::SetConfiguration(const ResTable_config& configuration) { } } -std::set<const ApkAssets*> AssetManager2::GetNonSystemOverlays() const { - std::set<const ApkAssets*> non_system_overlays; +std::set<AssetManager2::ApkAssetsPtr> AssetManager2::GetNonSystemOverlays() const { + std::set<ApkAssetsPtr> non_system_overlays; for (const PackageGroup& package_group : package_groups_) { bool found_system_package = false; for (const ConfiguredPackage& package : package_group.packages_) { @@ -410,8 +443,11 @@ std::set<const ApkAssets*> AssetManager2::GetNonSystemOverlays() const { } if (!found_system_package) { + auto op = StartOperation(); for (const ConfiguredOverlay& overlay : package_group.overlays_) { - non_system_overlays.insert(apk_assets_[overlay.cookie]); + if (const auto& asset = GetApkAssets(overlay.cookie)) { + non_system_overlays.insert(std::move(asset)); + } } } } @@ -422,22 +458,27 @@ std::set<const ApkAssets*> AssetManager2::GetNonSystemOverlays() const { base::expected<std::set<ResTable_config>, IOError> AssetManager2::GetResourceConfigurations( bool exclude_system, bool exclude_mipmap) const { ATRACE_NAME("AssetManager::GetResourceConfigurations"); + auto op = StartOperation(); + const auto non_system_overlays = - (exclude_system) ? GetNonSystemOverlays() : std::set<const ApkAssets*>(); + exclude_system ? GetNonSystemOverlays() : std::set<ApkAssetsPtr>(); std::set<ResTable_config> configurations; for (const PackageGroup& package_group : package_groups_) { for (size_t i = 0; i < package_group.packages_.size(); i++) { const ConfiguredPackage& package = package_group.packages_[i]; - if (exclude_system && package.loaded_package_->IsSystem()) { - continue; - } - - auto apk_assets = apk_assets_[package_group.cookies_[i]]; - if (exclude_system && apk_assets->IsOverlay() && - non_system_overlays.find(apk_assets) == non_system_overlays.end()) { - // Exclude overlays that target system resources. - continue; + if (exclude_system) { + if (package.loaded_package_->IsSystem()) { + continue; + } + if (!non_system_overlays.empty()) { + // Exclude overlays that target only system resources. + const auto& apk_assets = GetApkAssets(package_group.cookies_[i]); + if (apk_assets && apk_assets->IsOverlay() && + non_system_overlays.find(apk_assets) == non_system_overlays.end()) { + continue; + } + } } auto result = package.loaded_package_->CollectConfigurations(exclude_mipmap, &configurations); @@ -452,22 +493,27 @@ base::expected<std::set<ResTable_config>, IOError> AssetManager2::GetResourceCon std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system, bool merge_equivalent_languages) const { ATRACE_NAME("AssetManager::GetResourceLocales"); + auto op = StartOperation(); + std::set<std::string> locales; const auto non_system_overlays = - (exclude_system) ? GetNonSystemOverlays() : std::set<const ApkAssets*>(); + exclude_system ? GetNonSystemOverlays() : std::set<ApkAssetsPtr>(); for (const PackageGroup& package_group : package_groups_) { for (size_t i = 0; i < package_group.packages_.size(); i++) { const ConfiguredPackage& package = package_group.packages_[i]; - if (exclude_system && package.loaded_package_->IsSystem()) { - continue; - } - - auto apk_assets = apk_assets_[package_group.cookies_[i]]; - if (exclude_system && apk_assets->IsOverlay() && - non_system_overlays.find(apk_assets) == non_system_overlays.end()) { - // Exclude overlays that target system resources. - continue; + if (exclude_system) { + if (package.loaded_package_->IsSystem()) { + continue; + } + if (!non_system_overlays.empty()) { + // Exclude overlays that target only system resources. + const auto& apk_assets = GetApkAssets(package_group.cookies_[i]); + if (apk_assets && apk_assets->IsOverlay() && + non_system_overlays.find(apk_assets) == non_system_overlays.end()) { + continue; + } + } } package.loaded_package_->CollectLocales(merge_equivalent_languages, &locales); @@ -490,15 +536,15 @@ std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, ApkAsset std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) const { ATRACE_NAME("AssetManager::OpenDir"); + auto op = StartOperation(); std::string full_path = "assets/" + dirname; - std::unique_ptr<SortedVector<AssetDir::FileInfo>> files = - util::make_unique<SortedVector<AssetDir::FileInfo>>(); + auto files = util::make_unique<SortedVector<AssetDir::FileInfo>>(); // Start from the back. - for (auto iter = apk_assets_.rbegin(); iter != apk_assets_.rend(); ++iter) { - const ApkAssets* apk_assets = *iter; - if (apk_assets->IsOverlay()) { + for (size_t i = apk_assets_.size(); i > 0; --i) { + const auto& apk_assets = GetApkAssets(i - 1); + if (!apk_assets || apk_assets->IsOverlay()) { continue; } @@ -526,15 +572,17 @@ std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) con std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename, Asset::AccessMode mode, ApkAssetsCookie* out_cookie) const { - for (int32_t i = apk_assets_.size() - 1; i >= 0; i--) { + auto op = StartOperation(); + for (size_t i = apk_assets_.size(); i > 0; i--) { + const auto& assets = GetApkAssets(i - 1); // Prevent RRO from modifying assets and other entries accessed by file // path. Explicitly asking for a path in a given package (denoted by a // cookie) is still OK. - if (apk_assets_[i]->IsOverlay()) { + if (!assets || assets->IsOverlay()) { continue; } - std::unique_ptr<Asset> asset = apk_assets_[i]->GetAssetsProvider()->Open(filename, mode); + std::unique_ptr<Asset> asset = assets->GetAssetsProvider()->Open(filename, mode); if (asset) { if (out_cookie != nullptr) { *out_cookie = i; @@ -555,7 +603,9 @@ std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename, if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) { return {}; } - return apk_assets_[cookie]->GetAssetsProvider()->Open(filename, mode); + auto op = StartOperation(); + const auto& assets = GetApkAssets(cookie); + return assets ? assets->GetAssetsProvider()->Open(filename, mode) : nullptr; } base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( @@ -568,6 +618,8 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( last_resolution_.resid = resid; } + auto op = StartOperation(); + // Might use this if density_override != 0. ResTable_config density_override_config; @@ -603,90 +655,97 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( } bool overlaid = false; - if (!stop_at_first_match && !ignore_configuration && !apk_assets_[result->cookie]->IsLoader()) { - for (const auto& id_map : package_group.overlays_) { - auto overlay_entry = id_map.overlay_res_maps_.Lookup(resid); - if (!overlay_entry) { - // No id map entry exists for this target resource. - continue; - } - if (overlay_entry.IsInlineValue()) { - // The target resource is overlaid by an inline value not represented by a resource. - ConfigDescription best_frro_config; - Res_value best_frro_value; - bool frro_found = false; - for( const auto& [config, value] : overlay_entry.GetInlineValue()) { - if ((!frro_found || config.isBetterThan(best_frro_config, desired_config)) - && config.match(*desired_config)) { - frro_found = true; - best_frro_config = config; - best_frro_value = value; - } - } - if (!frro_found) { + if (!stop_at_first_match && !ignore_configuration) { + const auto& assets = GetApkAssets(result->cookie); + if (!assets) { + ALOGE("Found expired ApkAssets #%d for resource ID 0x%08x.", result->cookie, resid); + return base::unexpected(std::nullopt); + } + if (!assets->IsLoader()) { + for (const auto& id_map : package_group.overlays_) { + auto overlay_entry = id_map.overlay_res_maps_.Lookup(resid); + if (!overlay_entry) { + // No id map entry exists for this target resource. continue; } - result->entry = best_frro_value; - result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); - result->cookie = id_map.cookie; - - if (UNLIKELY(logging_enabled)) { - last_resolution_.steps.push_back( - Resolution::Step{Resolution::Step::Type::OVERLAID_INLINE, String8(), result->cookie}); - if (auto path = apk_assets_[result->cookie]->GetPath()) { - const std::string overlay_path = path->data(); - if (IsFabricatedOverlay(overlay_path)) { - // FRRO don't have package name so we use the creating package here. - String8 frro_name = String8("FRRO"); - // Get the first part of it since the expected one should be like - // {overlayPackageName}-{overlayName}-{4 alphanumeric chars}.frro - // under /data/resource-cache/. - const std::string name = overlay_path.substr(overlay_path.rfind('/') + 1); - const size_t end = name.find('-'); - if (frro_name.size() != overlay_path.size() && end != std::string::npos) { - frro_name.append(base::StringPrintf(" created by %s", - name.substr(0 /* pos */, - end).c_str()).c_str()); + if (overlay_entry.IsInlineValue()) { + // The target resource is overlaid by an inline value not represented by a resource. + ConfigDescription best_frro_config; + Res_value best_frro_value; + bool frro_found = false; + for( const auto& [config, value] : overlay_entry.GetInlineValue()) { + if ((!frro_found || config.isBetterThan(best_frro_config, desired_config)) + && config.match(*desired_config)) { + frro_found = true; + best_frro_config = config; + best_frro_value = value; + } + } + if (!frro_found) { + continue; + } + result->entry = best_frro_value; + result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); + result->cookie = id_map.cookie; + + if (UNLIKELY(logging_enabled)) { + last_resolution_.steps.push_back( + Resolution::Step{Resolution::Step::Type::OVERLAID_INLINE, String8(), result->cookie}); + if (auto path = assets->GetPath()) { + const std::string overlay_path = path->data(); + if (IsFabricatedOverlay(overlay_path)) { + // FRRO don't have package name so we use the creating package here. + String8 frro_name = String8("FRRO"); + // Get the first part of it since the expected one should be like + // {overlayPackageName}-{overlayName}-{4 alphanumeric chars}.frro + // under /data/resource-cache/. + const std::string name = overlay_path.substr(overlay_path.rfind('/') + 1); + const size_t end = name.find('-'); + if (frro_name.size() != overlay_path.size() && end != std::string::npos) { + frro_name.append(base::StringPrintf(" created by %s", + name.substr(0 /* pos */, + end).c_str()).c_str()); + } + last_resolution_.best_package_name = frro_name; + } else { + last_resolution_.best_package_name = result->package_name->c_str(); } - last_resolution_.best_package_name = frro_name; - } else { - last_resolution_.best_package_name = result->package_name->c_str(); } + overlaid = true; } - overlaid = true; + continue; } - continue; - } - auto overlay_result = FindEntry(overlay_entry.GetResourceId(), density_override, - false /* stop_at_first_match */, - false /* ignore_configuration */); - if (UNLIKELY(IsIOError(overlay_result))) { - return base::unexpected(overlay_result.error()); - } - if (!overlay_result.has_value()) { - continue; - } + auto overlay_result = FindEntry(overlay_entry.GetResourceId(), density_override, + false /* stop_at_first_match */, + false /* ignore_configuration */); + if (UNLIKELY(IsIOError(overlay_result))) { + return base::unexpected(overlay_result.error()); + } + if (!overlay_result.has_value()) { + continue; + } - if (!overlay_result->config.isBetterThan(result->config, desired_config) - && overlay_result->config.compare(result->config) != 0) { - // The configuration of the entry for the overlay must be equal to or better than the target - // configuration to be chosen as the better value. - continue; - } + if (!overlay_result->config.isBetterThan(result->config, desired_config) + && overlay_result->config.compare(result->config) != 0) { + // The configuration of the entry for the overlay must be equal to or better than the target + // configuration to be chosen as the better value. + continue; + } - result->cookie = overlay_result->cookie; - result->entry = overlay_result->entry; - result->config = overlay_result->config; - result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); + result->cookie = overlay_result->cookie; + result->entry = overlay_result->entry; + result->config = overlay_result->config; + result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); - if (UNLIKELY(logging_enabled)) { - last_resolution_.steps.push_back( - Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result->config.toString(), - overlay_result->cookie}); - last_resolution_.best_package_name = - overlay_result->package_name->c_str(); - overlaid = true; + if (UNLIKELY(logging_enabled)) { + last_resolution_.steps.push_back( + Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result->config.toString(), + overlay_result->cookie}); + last_resolution_.best_package_name = + overlay_result->package_name->c_str(); + overlaid = true; + } } } } @@ -839,13 +898,7 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntryInternal( } void AssetManager2::ResetResourceResolution() const { - last_resolution_.cookie = kInvalidCookie; - last_resolution_.resid = 0; - last_resolution_.steps.clear(); - last_resolution_.type_string_ref = StringPoolRef(); - last_resolution_.entry_string_ref = StringPoolRef(); - last_resolution_.best_config_name.clear(); - last_resolution_.best_package_name.clear(); + last_resolution_ = Resolution{}; } void AssetManager2::SetResourceResolutionLoggingEnabled(bool enabled) { @@ -867,8 +920,12 @@ std::string AssetManager2::GetLastResourceResolution() const { return {}; } + auto op = StartOperation(); + const uint32_t resid = last_resolution_.resid; - const auto package = apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid)); + const auto& assets = GetApkAssets(cookie); + const auto package = + assets ? assets->GetLoadedArsc()->GetPackageById(get_package_id(resid)) : nullptr; std::string resource_name_string; if (package != nullptr) { @@ -898,8 +955,9 @@ std::string AssetManager2::GetLastResourceResolution() const { if (prefix == kStepStrings.end()) { continue; } - - log_stream << "\n\t" << prefix->second << ": " << apk_assets_[step.cookie]->GetDebugName(); + const auto& assets = GetApkAssets(step.cookie); + log_stream << "\n\t" << prefix->second << ": " + << (assets ? assets->GetDebugName() : "<null>") << " #" << step.cookie; if (!step.config_name.empty()) { log_stream << " - " << step.config_name; } @@ -1429,6 +1487,37 @@ void AssetManager2::ForEachPackage(base::function_ref<bool(const std::string&, u } } +AssetManager2::ScopedOperation AssetManager2::StartOperation() const { + ++number_of_running_scoped_operations_; + return ScopedOperation(*this); +} + +void AssetManager2::FinishOperation() const { + if (number_of_running_scoped_operations_ < 1) { + ALOGW("Invalid FinishOperation() call when there's none happening"); + return; + } + if (--number_of_running_scoped_operations_ == 0) { + for (auto&& [_, assets] : apk_assets_) { + assets.clear(); + } + } +} + +const AssetManager2::ApkAssetsPtr& AssetManager2::GetApkAssets(ApkAssetsCookie cookie) const { + DCHECK(number_of_running_scoped_operations_ > 0) << "Must have an operation running"; + + if (cookie < 0 || cookie >= apk_assets_.size()) { + static const ApkAssetsPtr empty{}; + return empty; + } + auto& [wptr, res] = apk_assets_[cookie]; + if (!res) { + res = wptr.promote(); + } + return res; +} + Theme::Theme(AssetManager2* asset_manager) : asset_manager_(asset_manager) { } @@ -1561,14 +1650,16 @@ base::expected<std::monostate, IOError> Theme::SetTo(const Theme& source) { using SourceToDestinationRuntimePackageMap = std::unordered_map<int, int>; std::unordered_map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map; - // Determine which ApkAssets are loaded in both theme AssetManagers. - const auto& src_assets = source.asset_manager_->GetApkAssets(); - for (size_t i = 0; i < src_assets.size(); i++) { - const ApkAssets* src_asset = src_assets[i]; + auto op_src = source.asset_manager_->StartOperation(); + auto op_dst = asset_manager_->StartOperation(); - const auto& dest_assets = asset_manager_->GetApkAssets(); - for (size_t j = 0; j < dest_assets.size(); j++) { - const ApkAssets* dest_asset = dest_assets[j]; + for (size_t i = 0; i < source.asset_manager_->GetApkAssetsCount(); i++) { + const auto& src_asset = source.asset_manager_->GetApkAssets(i); + if (!src_asset) { + continue; + } + for (int j = 0; j < asset_manager_->GetApkAssetsCount(); j++) { + const auto& dest_asset = asset_manager_->GetApkAssets(j); if (src_asset != dest_asset) { // ResourcesManager caches and reuses ApkAssets when the same apk must be present in // multiple AssetManagers. Two ApkAssets point to the same version of the same resources @@ -1694,4 +1785,11 @@ void Theme::Dump() const { } } +AssetManager2::ScopedOperation::ScopedOperation(const AssetManager2& am) : am_(am) { +} + +AssetManager2::ScopedOperation::~ScopedOperation() { + am_.FinishOperation(); +} + } // namespace android diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp index c0fdfe25da21..fbfae5e2bcbe 100644 --- a/libs/androidfw/LoadedArsc.cpp +++ b/libs/androidfw/LoadedArsc.cpp @@ -323,7 +323,7 @@ LoadedPackage::GetEntryFromOffset(incfs::verified_map_ptr<ResTable_type> type_ch } base::expected<std::monostate, IOError> LoadedPackage::CollectConfigurations( - bool exclude_mipmap, std::set<ResTable_config>* out_configs) const {\ + bool exclude_mipmap, std::set<ResTable_config>* out_configs) const { for (const auto& type_spec : type_specs_) { if (exclude_mipmap) { const int type_idx = type_spec.first - 1; diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h index 6f88f41976cd..1fa67528c78b 100644 --- a/libs/androidfw/include/androidfw/ApkAssets.h +++ b/libs/androidfw/include/androidfw/ApkAssets.h @@ -17,12 +17,13 @@ #ifndef APKASSETS_H_ #define APKASSETS_H_ +#include <utils/RefBase.h> + #include <memory> #include <string> #include "android-base/macros.h" #include "android-base/unique_fd.h" - #include "androidfw/Asset.h" #include "androidfw/AssetsProvider.h" #include "androidfw/Idmap.h" @@ -31,34 +32,33 @@ namespace android { +class ApkAssets; + +using ApkAssetsPtr = sp<ApkAssets>; + // Holds an APK. -class ApkAssets { +class ApkAssets : public RefBase { public: // Creates an ApkAssets from a path on device. - static std::unique_ptr<ApkAssets> Load(const std::string& path, - package_property_t flags = 0U); + static ApkAssetsPtr Load(const std::string& path, package_property_t flags = 0U); // Creates an ApkAssets from an open file descriptor. - static std::unique_ptr<ApkAssets> LoadFromFd(base::unique_fd fd, - const std::string& debug_name, - package_property_t flags = 0U, - off64_t offset = 0, - off64_t len = AssetsProvider::kUnknownLength); + static ApkAssetsPtr LoadFromFd(base::unique_fd fd, const std::string& debug_name, + package_property_t flags = 0U, off64_t offset = 0, + off64_t len = AssetsProvider::kUnknownLength); // Creates an ApkAssets from an AssetProvider. // The ApkAssets will take care of destroying the AssetsProvider when it is destroyed. - static std::unique_ptr<ApkAssets> Load(std::unique_ptr<AssetsProvider> assets, - package_property_t flags = 0U); + static ApkAssetsPtr Load(std::unique_ptr<AssetsProvider> assets, package_property_t flags = 0U); // Creates an ApkAssets from the given asset file representing a resources.arsc. - static std::unique_ptr<ApkAssets> LoadTable(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<AssetsProvider> assets, - package_property_t flags = 0U); + static ApkAssetsPtr LoadTable(std::unique_ptr<Asset> resources_asset, + std::unique_ptr<AssetsProvider> assets, + package_property_t flags = 0U); // Creates an ApkAssets from an IDMAP, which contains the original APK path, and the overlay // data. - static std::unique_ptr<ApkAssets> LoadOverlay(const std::string& idmap_path, - package_property_t flags = 0U); + static ApkAssetsPtr LoadOverlay(const std::string& idmap_path, package_property_t flags = 0U); // Path to the contents of the ApkAssets on disk. The path could represent an APk, a directory, // or some other file type. @@ -95,22 +95,27 @@ class ApkAssets { bool IsUpToDate() const; private: - static std::unique_ptr<ApkAssets> LoadImpl(std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap); - - static std::unique_ptr<ApkAssets> LoadImpl(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap); - - ApkAssets(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<LoadedArsc> loaded_arsc, - std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, + static ApkAssetsPtr LoadImpl(std::unique_ptr<AssetsProvider> assets, + package_property_t property_flags, + std::unique_ptr<Asset> idmap_asset, + std::unique_ptr<LoadedIdmap> loaded_idmap); + + static ApkAssetsPtr LoadImpl(std::unique_ptr<Asset> resources_asset, + std::unique_ptr<AssetsProvider> assets, + package_property_t property_flags, + std::unique_ptr<Asset> idmap_asset, + std::unique_ptr<LoadedIdmap> loaded_idmap); + + // Allows us to make it possible to call make_shared from inside the class but still keeps the + // ctor 'private' for all means and purposes. + struct PrivateConstructorUtil { + explicit PrivateConstructorUtil() = default; + }; + + public: + ApkAssets(PrivateConstructorUtil, std::unique_ptr<Asset> resources_asset, + std::unique_ptr<LoadedArsc> loaded_arsc, std::unique_ptr<AssetsProvider> assets, + package_property_t property_flags, std::unique_ptr<Asset> idmap_asset, std::unique_ptr<LoadedIdmap> loaded_idmap); std::unique_ptr<Asset> resources_asset_; diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h index f10cb9bf480a..fc391bc2ce67 100644 --- a/libs/androidfw/include/androidfw/AssetManager2.h +++ b/libs/androidfw/include/androidfw/AssetManager2.h @@ -17,14 +17,16 @@ #ifndef ANDROIDFW_ASSETMANAGER2_H_ #define ANDROIDFW_ASSETMANAGER2_H_ -#include "android-base/function_ref.h" -#include "android-base/macros.h" +#include <utils/RefBase.h> #include <array> #include <limits> #include <set> +#include <span> #include <unordered_map> +#include "android-base/function_ref.h" +#include "android-base/macros.h" #include "androidfw/ApkAssets.h" #include "androidfw/Asset.h" #include "androidfw/AssetManager.h" @@ -94,8 +96,25 @@ class AssetManager2 { size_t entry_len = 0u; }; - AssetManager2(); + using ApkAssetsPtr = sp<const ApkAssets>; + using ApkAssetsWPtr = wp<const ApkAssets>; + using ApkAssetsList = std::span<const ApkAssetsPtr>; + + AssetManager2() = default; explicit AssetManager2(AssetManager2&& other) = default; + AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration); + + struct ScopedOperation { + DISALLOW_COPY_AND_ASSIGN(ScopedOperation); + friend AssetManager2; + const AssetManager2& am_; + ScopedOperation(const AssetManager2& am); + + public: + ~ScopedOperation(); + }; + + [[nodiscard]] ScopedOperation StartOperation() const; // Sets/resets the underlying ApkAssets for this AssetManager. The ApkAssets // are not owned by the AssetManager, and must have a longer lifetime. @@ -103,10 +122,12 @@ class AssetManager2 { // Only pass invalidate_caches=false when it is known that the structure // change in ApkAssets is due to a safe addition of resources with completely // new resource IDs. - bool SetApkAssets(std::vector<const ApkAssets*> apk_assets, bool invalidate_caches = true); + bool SetApkAssets(ApkAssetsList apk_assets, bool invalidate_caches = true); + bool SetApkAssets(std::initializer_list<ApkAssetsPtr> apk_assets, bool invalidate_caches = true); - inline const std::vector<const ApkAssets*>& GetApkAssets() const { - return apk_assets_; + const ApkAssetsPtr& GetApkAssets(ApkAssetsCookie cookie) const; + int GetApkAssetsCount() const { + return int(apk_assets_.size()); } // Returns the string pool for the given asset cookie. @@ -399,7 +420,7 @@ class AssetManager2 { // Assigns package IDs to all shared library ApkAssets. // Should be called whenever the ApkAssets are changed. - void BuildDynamicRefTable(); + void BuildDynamicRefTable(ApkAssetsList assets); // Purge all resources that are cached and vary by the configuration axis denoted by the // bitmask `diff`. @@ -410,16 +431,23 @@ class AssetManager2 { void RebuildFilterList(); // Retrieves the APK paths of overlays that overlay non-system packages. - std::set<const ApkAssets*> GetNonSystemOverlays() const; + std::set<ApkAssetsPtr> GetNonSystemOverlays() const; // AssetManager2::GetBag(resid) wraps this function to track which resource ids have already // been seen while traversing bag parents. base::expected<const ResolvedBag*, NullOrIOError> GetBag( uint32_t resid, std::vector<uint32_t>& child_resids) const; + // Finish an operation that was running with the current asset manager, and clean up the + // promoted apk assets when the last operation ends. + void FinishOperation() const; + // The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must // have a longer lifetime. - std::vector<const ApkAssets*> apk_assets_; + // The second pair element is the promoted version of the assets, that is held for the duration + // of the currently running operation. FinishOperation() clears all promoted assets to make sure + // they can be released when the system needs that. + mutable std::vector<std::pair<ApkAssetsWPtr, ApkAssetsPtr>> apk_assets_; // DynamicRefTables for shared library package resolution. // These are ordered according to apk_assets_. The mappings may change depending on what is @@ -433,7 +461,7 @@ class AssetManager2 { // The current configuration set for this AssetManager. When this changes, cached resources // may need to be purged. - ResTable_config configuration_; + ResTable_config configuration_ = {}; // Cached set of bags. These are cached because they can inherit keys from parent bags, // which involves some calculation. @@ -446,6 +474,10 @@ class AssetManager2 { // Cached set of resolved resource values. mutable std::unordered_map<uint32_t, SelectedValue> cached_resolved_values_; + // Tracking the number of the started operations running with the current AssetManager. + // Finishing the last one clears all promoted apk assets. + mutable int number_of_running_scoped_operations_ = 0; + // Whether or not to save resource resolution steps bool resource_resolution_logging_enabled_ = false; diff --git a/libs/androidfw/include/androidfw/MutexGuard.h b/libs/androidfw/include/androidfw/MutexGuard.h index 6fc6d64e2f6e..b6093dbb6d3d 100644 --- a/libs/androidfw/include/androidfw/MutexGuard.h +++ b/libs/androidfw/include/androidfw/MutexGuard.h @@ -14,12 +14,12 @@ * limitations under the License. */ -#ifndef ANDROIDFW_MUTEXGUARD_H -#define ANDROIDFW_MUTEXGUARD_H +#pragma once #include <mutex> #include <optional> #include <type_traits> +#include <utility> #include "android-base/macros.h" @@ -45,20 +45,25 @@ class ScopedLock; // template <typename T> class Guarded { - static_assert(!std::is_pointer<T>::value, "T must not be a raw pointer"); + static_assert(!std::is_pointer_v<T>, "T must not be a raw pointer"); public: - Guarded() : guarded_(std::in_place, T()) { + Guarded() : guarded_(std::in_place) { } explicit Guarded(const T& guarded) : guarded_(std::in_place, guarded) { } - explicit Guarded(T&& guarded) : guarded_(std::in_place, std::forward<T>(guarded)) { + explicit Guarded(T&& guarded) : guarded_(std::in_place, std::move(guarded)) { } - ~Guarded() { - std::lock_guard<std::mutex> scoped_lock(lock_); + // Unfortunately, some legacy designs make even class deletion race-prone, where some other + // thread may have not finished working with the same object. For those cases one may destroy the + // object under a lock (but please fix your code, at least eventually!). + template <class Func> + void safeDelete(Func f) { + std::lock_guard scoped_lock(lock_); + f(guarded_ ? &guarded_.value() : nullptr); guarded_.reset(); } @@ -96,5 +101,3 @@ class ScopedLock { }; } // namespace android - -#endif // ANDROIDFW_MUTEXGUARD_H diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp index 19db25ce8811..70326b71da28 100644 --- a/libs/androidfw/tests/ApkAssets_test.cpp +++ b/libs/androidfw/tests/ApkAssets_test.cpp @@ -35,8 +35,7 @@ using ::testing::StrEq; namespace android { TEST(ApkAssetsTest, LoadApk) { - std::unique_ptr<const ApkAssets> loaded_apk = - ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); + auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); ASSERT_THAT(loaded_apk, NotNull()); const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc(); @@ -50,7 +49,7 @@ TEST(ApkAssetsTest, LoadApkFromFd) { unique_fd fd(::open(path.c_str(), O_RDONLY | O_BINARY)); ASSERT_THAT(fd.get(), Ge(0)); - std::unique_ptr<const ApkAssets> loaded_apk = ApkAssets::LoadFromFd(std::move(fd), path); + auto loaded_apk = ApkAssets::LoadFromFd(std::move(fd), path); ASSERT_THAT(loaded_apk, NotNull()); const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc(); @@ -60,8 +59,7 @@ TEST(ApkAssetsTest, LoadApkFromFd) { } TEST(ApkAssetsTest, LoadApkAsSharedLibrary) { - std::unique_ptr<const ApkAssets> loaded_apk = - ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk"); + auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk"); ASSERT_THAT(loaded_apk, NotNull()); const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc(); @@ -79,8 +77,7 @@ TEST(ApkAssetsTest, LoadApkAsSharedLibrary) { } TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) { - std::unique_ptr<const ApkAssets> loaded_apk = - ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); + auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); ASSERT_THAT(loaded_apk, NotNull()); { ASSERT_THAT(loaded_apk->GetAssetsProvider()->Open("res/layout/main.xml", @@ -91,8 +88,7 @@ TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) { } TEST(ApkAssetsTest, OpenUncompressedAssetFd) { - std::unique_ptr<const ApkAssets> loaded_apk = - ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); + auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); ASSERT_THAT(loaded_apk, NotNull()); auto asset = loaded_apk->GetAssetsProvider()->Open("assets/uncompressed.txt", diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp index c7ae618991b9..6fae72a6d10e 100644 --- a/libs/androidfw/tests/AssetManager2_bench.cpp +++ b/libs/androidfw/tests/AssetManager2_bench.cpp @@ -38,9 +38,9 @@ constexpr const static char* kFrameworkPath = "/system/framework/framework-res.a static void BM_AssetManagerLoadAssets(benchmark::State& state) { std::string path = GetTestDataPath() + "/basic/basic.apk"; while (state.KeepRunning()) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path); + auto apk = ApkAssets::Load(path); AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); } } BENCHMARK(BM_AssetManagerLoadAssets); @@ -61,9 +61,9 @@ BENCHMARK(BM_AssetManagerLoadAssetsOld); static void BM_AssetManagerLoadFrameworkAssets(benchmark::State& state) { std::string path = kFrameworkPath; while (state.KeepRunning()) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path); + auto apk = ApkAssets::Load(path); AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); } } BENCHMARK(BM_AssetManagerLoadFrameworkAssets); @@ -129,14 +129,14 @@ static void BM_AssetManagerGetResourceFrameworkLocaleOld(benchmark::State& state BENCHMARK(BM_AssetManagerGetResourceFrameworkLocaleOld); static void BM_AssetManagerGetBag(benchmark::State& state) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); + auto apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); if (apk == nullptr) { state.SkipWithError("Failed to load assets"); return; } AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); while (state.KeepRunning()) { auto bag = assets.GetBag(app::R::style::StyleTwo); @@ -181,14 +181,14 @@ static void BM_AssetManagerGetBagOld(benchmark::State& state) { BENCHMARK(BM_AssetManagerGetBagOld); static void BM_AssetManagerGetResourceLocales(benchmark::State& state) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath); + auto apk = ApkAssets::Load(kFrameworkPath); if (apk == nullptr) { state.SkipWithError("Failed to load assets"); return; } AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); while (state.KeepRunning()) { std::set<std::string> locales = @@ -217,14 +217,14 @@ static void BM_AssetManagerGetResourceLocalesOld(benchmark::State& state) { BENCHMARK(BM_AssetManagerGetResourceLocalesOld); static void BM_AssetManagerSetConfigurationFramework(benchmark::State& state) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath); + auto apk = ApkAssets::Load(kFrameworkPath); if (apk == nullptr) { state.SkipWithError("Failed to load assets"); return; } AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); ResTable_config config; memset(&config, 0, sizeof(config)); diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp index 4394740e44ba..df3fa02ce44c 100644 --- a/libs/androidfw/tests/AssetManager2_test.cpp +++ b/libs/androidfw/tests/AssetManager2_test.cpp @@ -91,19 +91,19 @@ class AssetManager2Test : public ::testing::Test { } protected: - std::unique_ptr<const ApkAssets> basic_assets_; - std::unique_ptr<const ApkAssets> basic_de_fr_assets_; - std::unique_ptr<const ApkAssets> basic_xhdpi_assets_; - std::unique_ptr<const ApkAssets> basic_xxhdpi_assets_; - std::unique_ptr<const ApkAssets> style_assets_; - std::unique_ptr<const ApkAssets> lib_one_assets_; - std::unique_ptr<const ApkAssets> lib_two_assets_; - std::unique_ptr<const ApkAssets> libclient_assets_; - std::unique_ptr<const ApkAssets> appaslib_assets_; - std::unique_ptr<const ApkAssets> system_assets_; - std::unique_ptr<const ApkAssets> app_assets_; - std::unique_ptr<const ApkAssets> overlay_assets_; - std::unique_ptr<const ApkAssets> overlayable_assets_; + AssetManager2::ApkAssetsPtr basic_assets_; + AssetManager2::ApkAssetsPtr basic_de_fr_assets_; + AssetManager2::ApkAssetsPtr basic_xhdpi_assets_; + AssetManager2::ApkAssetsPtr basic_xxhdpi_assets_; + AssetManager2::ApkAssetsPtr style_assets_; + AssetManager2::ApkAssetsPtr lib_one_assets_; + AssetManager2::ApkAssetsPtr lib_two_assets_; + AssetManager2::ApkAssetsPtr libclient_assets_; + AssetManager2::ApkAssetsPtr appaslib_assets_; + AssetManager2::ApkAssetsPtr system_assets_; + AssetManager2::ApkAssetsPtr app_assets_; + AssetManager2::ApkAssetsPtr overlay_assets_; + AssetManager2::ApkAssetsPtr overlayable_assets_; }; TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) { @@ -114,7 +114,7 @@ TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) { AssetManager2 assetmanager; assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); ASSERT_TRUE(value.has_value()); @@ -138,7 +138,7 @@ TEST_F(AssetManager2Test, FindsResourceFromMultipleApkAssets) { AssetManager2 assetmanager; assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get(), basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); ASSERT_TRUE(value.has_value()); @@ -159,8 +159,7 @@ TEST_F(AssetManager2Test, FindsResourceFromSharedLibrary) { // libclient is built with lib_one and then lib_two in order. // Reverse the order to test that proper package ID re-assignment is happening. - assetmanager.SetApkAssets( - {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); + assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_}); auto value = assetmanager.GetResource(libclient::R::string::foo_one); ASSERT_TRUE(value.has_value()); @@ -195,7 +194,7 @@ TEST_F(AssetManager2Test, FindsResourceFromSharedLibrary) { TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({appaslib_assets_.get()}); + assetmanager.SetApkAssets({appaslib_assets_}); // The appaslib package will have been assigned the package ID 0x02. auto value = assetmanager.GetResource(fix_package_id(appaslib::R::integer::number1, 0x02)); @@ -206,27 +205,26 @@ TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) { TEST_F(AssetManager2Test, AssignsOverlayPackageIdLast) { AssetManager2 assetmanager; - assetmanager.SetApkAssets( - {overlayable_assets_.get(), overlay_assets_.get(), lib_one_assets_.get()}); + assetmanager.SetApkAssets({overlayable_assets_, overlay_assets_, lib_one_assets_}); - auto apk_assets = assetmanager.GetApkAssets(); - ASSERT_EQ(3, apk_assets.size()); - ASSERT_EQ(overlayable_assets_.get(), apk_assets[0]); - ASSERT_EQ(overlay_assets_.get(), apk_assets[1]); - ASSERT_EQ(lib_one_assets_.get(), apk_assets[2]); + ASSERT_EQ(3, assetmanager.GetApkAssetsCount()); + auto op = assetmanager.StartOperation(); + ASSERT_EQ(overlayable_assets_, assetmanager.GetApkAssets(0)); + ASSERT_EQ(overlay_assets_, assetmanager.GetApkAssets(1)); + ASSERT_EQ(lib_one_assets_, assetmanager.GetApkAssets(2)); - auto get_first_package_id = [&assetmanager](const ApkAssets* apkAssets) -> uint8_t { + auto get_first_package_id = [&assetmanager](auto apkAssets) -> uint8_t { return assetmanager.GetAssignedPackageId(apkAssets->GetLoadedArsc()->GetPackages()[0].get()); }; - ASSERT_EQ(0x7f, get_first_package_id(overlayable_assets_.get())); - ASSERT_EQ(0x03, get_first_package_id(overlay_assets_.get())); - ASSERT_EQ(0x02, get_first_package_id(lib_one_assets_.get())); + ASSERT_EQ(0x7f, get_first_package_id(overlayable_assets_)); + ASSERT_EQ(0x03, get_first_package_id(overlay_assets_)); + ASSERT_EQ(0x02, get_first_package_id(lib_one_assets_)); } TEST_F(AssetManager2Test, GetSharedLibraryResourceName) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({lib_one_assets_.get()}); + assetmanager.SetApkAssets({lib_one_assets_}); auto name = assetmanager.GetResourceName(lib_one::R::string::foo); ASSERT_TRUE(name.has_value()); @@ -235,7 +233,7 @@ TEST_F(AssetManager2Test, GetSharedLibraryResourceName) { TEST_F(AssetManager2Test, GetResourceNameNonMatchingConfig) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({basic_de_fr_assets_}); auto value = assetmanager.GetResourceName(basic::R::string::test1); ASSERT_TRUE(value.has_value()); @@ -244,7 +242,7 @@ TEST_F(AssetManager2Test, GetResourceNameNonMatchingConfig) { TEST_F(AssetManager2Test, GetResourceTypeSpecFlags) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({basic_de_fr_assets_}); auto value = assetmanager.GetResourceTypeSpecFlags(basic::R::string::test1); ASSERT_TRUE(value.has_value()); @@ -253,7 +251,7 @@ TEST_F(AssetManager2Test, GetResourceTypeSpecFlags) { TEST_F(AssetManager2Test, FindsBagResourceFromSingleApkAssets) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto bag = assetmanager.GetBag(basic::R::array::integerArray1); ASSERT_TRUE(bag.has_value()); @@ -280,8 +278,7 @@ TEST_F(AssetManager2Test, FindsBagResourceFromSharedLibrary) { // libclient is built with lib_one and then lib_two in order. // Reverse the order to test that proper package ID re-assignment is happening. - assetmanager.SetApkAssets( - {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); + assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_}); auto bag = assetmanager.GetBag(fix_package_id(lib_one::R::style::Theme, 0x03)); ASSERT_TRUE(bag.has_value()); @@ -300,8 +297,7 @@ TEST_F(AssetManager2Test, FindsBagResourceFromMultipleSharedLibraries) { // libclient is built with lib_one and then lib_two in order. // Reverse the order to test that proper package ID re-assignment is happening. - assetmanager.SetApkAssets( - {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); + assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_}); auto bag = assetmanager.GetBag(libclient::R::style::ThemeMultiLib); ASSERT_TRUE(bag.has_value()); @@ -321,8 +317,7 @@ TEST_F(AssetManager2Test, FindsStyleResourceWithParentFromSharedLibrary) { // libclient is built with lib_one and then lib_two in order. // Reverse the order to test that proper package ID re-assignment is happening. - assetmanager.SetApkAssets( - {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); + assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_}); auto bag = assetmanager.GetBag(libclient::R::style::Theme); ASSERT_TRUE(bag.has_value()); @@ -337,7 +332,7 @@ TEST_F(AssetManager2Test, FindsStyleResourceWithParentFromSharedLibrary) { TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); auto bag_one = assetmanager.GetBag(app::R::style::StyleOne); ASSERT_TRUE(bag_one.has_value()); @@ -401,7 +396,7 @@ TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) { TEST_F(AssetManager2Test, MergeStylesCircularDependency) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); // GetBag should stop traversing the parents of styles when a circular // dependency is detected @@ -412,7 +407,7 @@ TEST_F(AssetManager2Test, MergeStylesCircularDependency) { TEST_F(AssetManager2Test, ResolveReferenceToResource) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::integer::ref1); ASSERT_TRUE(value.has_value()); @@ -428,7 +423,7 @@ TEST_F(AssetManager2Test, ResolveReferenceToResource) { TEST_F(AssetManager2Test, ResolveReferenceToBag) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::integer::number2, true /*may_be_bag*/); ASSERT_TRUE(value.has_value()); @@ -444,7 +439,7 @@ TEST_F(AssetManager2Test, ResolveReferenceToBag) { TEST_F(AssetManager2Test, ResolveDeepIdReference) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); // Set up the resource ids auto high_ref = assetmanager.GetResourceId("@id/high_ref", "values", "com.android.basic"); @@ -470,8 +465,7 @@ TEST_F(AssetManager2Test, ResolveDeepIdReference) { TEST_F(AssetManager2Test, DensityOverride) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get(), basic_xhdpi_assets_.get(), - basic_xxhdpi_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_, basic_xhdpi_assets_, basic_xxhdpi_assets_}); assetmanager.SetConfiguration({ .density = ResTable_config::DENSITY_XHIGH, .sdkVersion = 21, @@ -493,7 +487,7 @@ TEST_F(AssetManager2Test, DensityOverride) { TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); // Create some kind of value that is NOT a reference. AssetManager2::SelectedValue value{}; @@ -509,7 +503,7 @@ TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved) TEST_F(AssetManager2Test, ResolveReferenceMissingResourceDoNotCacheFlags) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); { AssetManager2::SelectedValue value{}; value.data = basic::R::string::test1; @@ -540,7 +534,7 @@ TEST_F(AssetManager2Test, ResolveReferenceMissingResourceDoNotCacheFlags) { TEST_F(AssetManager2Test, ResolveReferenceMissingResource) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); const uint32_t kMissingResId = 0x8001ffff; AssetManager2::SelectedValue value{}; @@ -558,7 +552,7 @@ TEST_F(AssetManager2Test, ResolveReferenceMissingResource) { TEST_F(AssetManager2Test, ResolveReferenceMissingResourceLib) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({libclient_assets_.get()}); + assetmanager.SetApkAssets({libclient_assets_}); AssetManager2::SelectedValue value{}; value.type = Res_value::TYPE_REFERENCE; @@ -580,7 +574,7 @@ static bool IsConfigurationPresent(const std::set<ResTable_config>& configuratio TEST_F(AssetManager2Test, GetResourceConfigurations) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get(), basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({system_assets_, basic_de_fr_assets_}); auto configurations = assetmanager.GetResourceConfigurations(); ASSERT_TRUE(configurations.has_value()); @@ -625,7 +619,7 @@ TEST_F(AssetManager2Test, GetResourceConfigurations) { TEST_F(AssetManager2Test, GetResourceLocales) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get(), basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({system_assets_, basic_de_fr_assets_}); std::set<std::string> locales = assetmanager.GetResourceLocales(); @@ -644,7 +638,7 @@ TEST_F(AssetManager2Test, GetResourceLocales) { TEST_F(AssetManager2Test, GetResourceId) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto resid = assetmanager.GetResourceId("com.android.basic:layout/main", "", ""); ASSERT_TRUE(resid.has_value()); @@ -661,7 +655,7 @@ TEST_F(AssetManager2Test, GetResourceId) { TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get()}); + assetmanager.SetApkAssets({system_assets_}); std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER); ASSERT_THAT(asset, NotNull()); @@ -673,7 +667,7 @@ TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) { TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()}); + assetmanager.SetApkAssets({system_assets_, app_assets_}); std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER); ASSERT_THAT(asset, NotNull()); @@ -685,7 +679,7 @@ TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) { TEST_F(AssetManager2Test, OpenDir) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get()}); + assetmanager.SetApkAssets({system_assets_}); std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir(""); ASSERT_THAT(asset_dir, NotNull()); @@ -707,7 +701,7 @@ TEST_F(AssetManager2Test, OpenDir) { TEST_F(AssetManager2Test, OpenDirFromManyApks) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()}); + assetmanager.SetApkAssets({system_assets_, app_assets_}); std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir(""); ASSERT_THAT(asset_dir, NotNull()); @@ -728,7 +722,7 @@ TEST_F(AssetManager2Test, GetLastPathWithoutEnablingReturnsEmpty) { AssetManager2 assetmanager; assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); assetmanager.SetResourceResolutionLoggingEnabled(false); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -743,7 +737,7 @@ TEST_F(AssetManager2Test, GetLastPathWithoutResolutionReturnsEmpty) { AssetManager2 assetmanager; assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto result = assetmanager.GetLastResourceResolution(); EXPECT_EQ("", result); @@ -758,17 +752,18 @@ TEST_F(AssetManager2Test, GetLastPathWithSingleApkAssets) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); ASSERT_TRUE(value.has_value()); auto result = assetmanager.GetLastResourceResolution(); - EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n" - "\tFor config - de\n" - "\tFound initial: basic/basic.apk\n" - "Best matching is from default configuration of com.android.basic", - result); + EXPECT_EQ( + "Resolution for 0x7f030000 com.android.basic:string/test1\n" + "\tFor config - de\n" + "\tFound initial: basic/basic.apk #0\n" + "Best matching is from default configuration of com.android.basic", + result); } TEST_F(AssetManager2Test, GetLastPathWithMultipleApkAssets) { @@ -780,18 +775,19 @@ TEST_F(AssetManager2Test, GetLastPathWithMultipleApkAssets) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get(), basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); ASSERT_TRUE(value.has_value()); auto result = assetmanager.GetLastResourceResolution(); - EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n" - "\tFor config - de\n" - "\tFound initial: basic/basic.apk\n" - "\tFound better: basic/basic_de_fr.apk - de\n" - "Best matching is from de configuration of com.android.basic", - result); + EXPECT_EQ( + "Resolution for 0x7f030000 com.android.basic:string/test1\n" + "\tFor config - de\n" + "\tFound initial: basic/basic.apk #0\n" + "\tFound better: basic/basic_de_fr.apk #1 - de\n" + "Best matching is from de configuration of com.android.basic", + result); } TEST_F(AssetManager2Test, GetLastPathAfterDisablingReturnsEmpty) { @@ -801,7 +797,7 @@ TEST_F(AssetManager2Test, GetLastPathAfterDisablingReturnsEmpty) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); ASSERT_TRUE(value.has_value()); @@ -822,7 +818,7 @@ TEST_F(AssetManager2Test, GetOverlayablesToString) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({overlayable_assets_.get()}); + assetmanager.SetApkAssets({overlayable_assets_}); const auto map = assetmanager.GetOverlayableMapForPackage(0x7f); ASSERT_NE(nullptr, map); @@ -838,4 +834,26 @@ TEST_F(AssetManager2Test, GetOverlayablesToString) { std::string::npos); } +TEST_F(AssetManager2Test, GetApkAssets) { + AssetManager2 assetmanager; + assetmanager.SetApkAssets({overlayable_assets_, overlay_assets_, lib_one_assets_}); + + ASSERT_EQ(3, assetmanager.GetApkAssetsCount()); + EXPECT_EQ(1, overlayable_assets_->getStrongCount()); + EXPECT_EQ(1, overlay_assets_->getStrongCount()); + EXPECT_EQ(1, lib_one_assets_->getStrongCount()); + + { + auto op = assetmanager.StartOperation(); + ASSERT_EQ(overlayable_assets_, assetmanager.GetApkAssets(0)); + ASSERT_EQ(overlay_assets_, assetmanager.GetApkAssets(1)); + EXPECT_EQ(2, overlayable_assets_->getStrongCount()); + EXPECT_EQ(2, overlay_assets_->getStrongCount()); + EXPECT_EQ(1, lib_one_assets_->getStrongCount()); + } + EXPECT_EQ(1, overlayable_assets_->getStrongCount()); + EXPECT_EQ(1, overlay_assets_->getStrongCount()); + EXPECT_EQ(1, lib_one_assets_->getStrongCount()); +} + } // namespace android diff --git a/libs/androidfw/tests/AttributeResolution_bench.cpp b/libs/androidfw/tests/AttributeResolution_bench.cpp index 1c89c61c8f78..384f4a78b36d 100644 --- a/libs/androidfw/tests/AttributeResolution_bench.cpp +++ b/libs/androidfw/tests/AttributeResolution_bench.cpp @@ -36,15 +36,14 @@ constexpr const static char* kFrameworkPath = "/system/framework/framework-res.a constexpr const static uint32_t Theme_Material_Light = 0x01030237u; static void BM_ApplyStyle(benchmark::State& state) { - std::unique_ptr<const ApkAssets> styles_apk = - ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); + auto styles_apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); if (styles_apk == nullptr) { state.SkipWithError("failed to load assets"); return; } AssetManager2 assetmanager; - assetmanager.SetApkAssets({styles_apk.get()}); + assetmanager.SetApkAssets({styles_apk}); std::unique_ptr<Asset> asset = assetmanager.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER); @@ -80,21 +79,20 @@ static void BM_ApplyStyle(benchmark::State& state) { BENCHMARK(BM_ApplyStyle); static void BM_ApplyStyleFramework(benchmark::State& state) { - std::unique_ptr<const ApkAssets> framework_apk = ApkAssets::Load(kFrameworkPath); + auto framework_apk = ApkAssets::Load(kFrameworkPath); if (framework_apk == nullptr) { state.SkipWithError("failed to load framework assets"); return; } - std::unique_ptr<const ApkAssets> basic_apk = - ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); + auto basic_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); if (basic_apk == nullptr) { state.SkipWithError("failed to load assets"); return; } AssetManager2 assetmanager; - assetmanager.SetApkAssets({framework_apk.get(), basic_apk.get()}); + assetmanager.SetApkAssets({framework_apk, basic_apk}); ResTable_config device_config; memset(&device_config, 0, sizeof(device_config)); diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp index bb9129ad01c8..329830fa47b2 100644 --- a/libs/androidfw/tests/AttributeResolution_test.cpp +++ b/libs/androidfw/tests/AttributeResolution_test.cpp @@ -36,11 +36,11 @@ class AttributeResolutionTest : public ::testing::Test { virtual void SetUp() override { styles_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); ASSERT_NE(nullptr, styles_assets_); - assetmanager_.SetApkAssets({styles_assets_.get()}); + assetmanager_.SetApkAssets({styles_assets_}); } protected: - std::unique_ptr<const ApkAssets> styles_assets_; + AssetManager2::ApkAssetsPtr styles_assets_; AssetManager2 assetmanager_; }; @@ -69,7 +69,7 @@ TEST(AttributeResolutionLibraryTest, ApplyStyleWithDefaultStyleResId) { AssetManager2 assetmanager; auto apk_assets = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk", PROPERTY_DYNAMIC); ASSERT_NE(nullptr, apk_assets); - assetmanager.SetApkAssets({apk_assets.get()}); + assetmanager.SetApkAssets({apk_assets}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); diff --git a/libs/androidfw/tests/BenchmarkHelpers.cpp b/libs/androidfw/tests/BenchmarkHelpers.cpp index 0fa0573bcbb8..b97dd96f8934 100644 --- a/libs/androidfw/tests/BenchmarkHelpers.cpp +++ b/libs/androidfw/tests/BenchmarkHelpers.cpp @@ -53,20 +53,18 @@ void GetResourceBenchmarkOld(const std::vector<std::string>& paths, const ResTab void GetResourceBenchmark(const std::vector<std::string>& paths, const ResTable_config* config, uint32_t resid, benchmark::State& state) { - std::vector<std::unique_ptr<const ApkAssets>> apk_assets; - std::vector<const ApkAssets*> apk_assets_ptrs; + std::vector<AssetManager2::ApkAssetsPtr> apk_assets; for (const std::string& path : paths) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path); + auto apk = ApkAssets::Load(path); if (apk == nullptr) { state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str()); return; } - apk_assets_ptrs.push_back(apk.get()); apk_assets.push_back(std::move(apk)); } AssetManager2 assetmanager; - assetmanager.SetApkAssets(apk_assets_ptrs); + assetmanager.SetApkAssets(apk_assets); if (config != nullptr) { assetmanager.SetConfiguration(*config); } diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp index b43491548e2b..60aa7d88925d 100644 --- a/libs/androidfw/tests/Idmap_test.cpp +++ b/libs/androidfw/tests/Idmap_test.cpp @@ -59,15 +59,16 @@ class IdmapTest : public ::testing::Test { protected: std::string original_path; - std::unique_ptr<const ApkAssets> system_assets_; - std::unique_ptr<const ApkAssets> overlay_assets_; - std::unique_ptr<const ApkAssets> overlayable_assets_; + AssetManager2::ApkAssetsPtr system_assets_; + AssetManager2::ApkAssetsPtr overlay_assets_; + AssetManager2::ApkAssetsPtr overlayable_assets_; }; std::string GetStringFromApkAssets(const AssetManager2& asset_manager, const AssetManager2::SelectedValue& value) { - auto assets = asset_manager.GetApkAssets(); - const ResStringPool* string_pool = assets[value.cookie]->GetLoadedArsc()->GetStringPool(); + auto op = asset_manager.StartOperation(); + const ResStringPool* string_pool = + asset_manager.GetApkAssets(value.cookie)->GetLoadedArsc()->GetStringPool(); return GetStringFromPool(string_pool, value.data); } @@ -75,8 +76,7 @@ std::string GetStringFromApkAssets(const AssetManager2& asset_manager, TEST_F(IdmapTest, OverlayOverridesResourceValue) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable5); ASSERT_TRUE(value.has_value()); @@ -87,8 +87,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValue) { TEST_F(IdmapTest, OverlayOverridesResourceValueUsingDifferentPackage) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable10); ASSERT_TRUE(value.has_value()); @@ -99,8 +98,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValueUsingDifferentPackage) { TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInternalResource) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable8); ASSERT_TRUE(value.has_value()); @@ -111,8 +109,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInternalResource) { TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineInteger) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::integer::config_integer); ASSERT_TRUE(value.has_value()); @@ -123,8 +120,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineInteger) { TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineString) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable11); ASSERT_TRUE(value.has_value()); @@ -135,8 +131,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineString) { TEST_F(IdmapTest, OverlayOverridesResourceValueUsingOverlayingResource) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable9); ASSERT_TRUE(value.has_value()); @@ -147,8 +142,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValueUsingOverlayingResource) { TEST_F(IdmapTest, OverlayOverridesXmlParser) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::layout::hello_view); ASSERT_TRUE(value.has_value()); @@ -186,8 +180,7 @@ TEST_F(IdmapTest, OverlayOverridesXmlParser) { TEST_F(IdmapTest, OverlaidResourceHasSameName) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto name = asset_manager.GetResourceName(overlayable::R::string::overlayable9); ASSERT_TRUE(name.has_value()); @@ -203,8 +196,7 @@ TEST_F(IdmapTest, OverlayLoaderInterop) { auto loader_assets = ApkAssets::LoadTable(std::move(asset), EmptyAssetsProvider::Create(), PROPERTY_LOADER); AssetManager2 asset_manager; - asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({overlayable_assets_, loader_assets, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable11); ASSERT_TRUE(value.has_value()); diff --git a/libs/androidfw/tests/Theme_bench.cpp b/libs/androidfw/tests/Theme_bench.cpp index f3d60bbe4f15..dfbb5a76dec6 100644 --- a/libs/androidfw/tests/Theme_bench.cpp +++ b/libs/androidfw/tests/Theme_bench.cpp @@ -28,14 +28,14 @@ constexpr const static uint32_t kStyleId = 0x01030237u; // android:style/Theme. constexpr const static uint32_t kAttrId = 0x01010030u; // android:attr/colorForeground static void BM_ThemeApplyStyleFramework(benchmark::State& state) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath); + auto apk = ApkAssets::Load(kFrameworkPath); if (apk == nullptr) { state.SkipWithError("Failed to load assets"); return; } AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); while (state.KeepRunning()) { auto theme = assets.NewTheme(); @@ -62,10 +62,10 @@ static void BM_ThemeApplyStyleFrameworkOld(benchmark::State& state) { BENCHMARK(BM_ThemeApplyStyleFrameworkOld); static void BM_ThemeGetAttribute(benchmark::State& state) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath); + auto apk = ApkAssets::Load(kFrameworkPath); AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); auto theme = assets.NewTheme(); theme->ApplyStyle(kStyleId, false /* force */); diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp index 77114f273d3d..e08a6a7f277d 100644 --- a/libs/androidfw/tests/Theme_test.cpp +++ b/libs/androidfw/tests/Theme_test.cpp @@ -53,16 +53,16 @@ class ThemeTest : public ::testing::Test { } protected: - std::unique_ptr<const ApkAssets> system_assets_; - std::unique_ptr<const ApkAssets> style_assets_; - std::unique_ptr<const ApkAssets> libclient_assets_; - std::unique_ptr<const ApkAssets> lib_one_assets_; - std::unique_ptr<const ApkAssets> lib_two_assets_; + AssetManager2::ApkAssetsPtr system_assets_; + AssetManager2::ApkAssetsPtr style_assets_; + AssetManager2::ApkAssetsPtr libclient_assets_; + AssetManager2::ApkAssetsPtr lib_one_assets_; + AssetManager2::ApkAssetsPtr lib_two_assets_; }; TEST_F(ThemeTest, EmptyTheme) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); EXPECT_EQ(0u, theme->GetChangingConfigurations()); @@ -72,7 +72,7 @@ TEST_F(ThemeTest, EmptyTheme) { TEST_F(ThemeTest, SingleThemeNoParent) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleOne).has_value()); @@ -92,7 +92,7 @@ TEST_F(ThemeTest, SingleThemeNoParent) { TEST_F(ThemeTest, SingleThemeWithParent) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value()); @@ -121,7 +121,7 @@ TEST_F(ThemeTest, SingleThemeWithParent) { TEST_F(ThemeTest, TryToUseBadResourceId) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value()); @@ -130,7 +130,7 @@ TEST_F(ThemeTest, TryToUseBadResourceId) { TEST_F(ThemeTest, MultipleThemesOverlaidNotForce) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value()); @@ -160,7 +160,7 @@ TEST_F(ThemeTest, MultipleThemesOverlaidNotForce) { TEST_F(ThemeTest, MultipleThemesOverlaidForced) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value()); @@ -190,8 +190,7 @@ TEST_F(ThemeTest, MultipleThemesOverlaidForced) { TEST_F(ThemeTest, ResolveDynamicAttributesAndReferencesToSharedLibrary) { AssetManager2 assetmanager; - assetmanager.SetApkAssets( - {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); + assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(libclient::R::style::Theme, false /*force*/).has_value()); @@ -216,7 +215,7 @@ TEST_F(ThemeTest, ResolveDynamicAttributesAndReferencesToSharedLibrary) { TEST_F(ThemeTest, CopyThemeSameAssetManager) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme_one = assetmanager.NewTheme(); ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne).has_value()); @@ -253,10 +252,10 @@ TEST_F(ThemeTest, CopyThemeSameAssetManager) { TEST_F(ThemeTest, ThemeRebase) { AssetManager2 am; - am.SetApkAssets({style_assets_.get()}); + am.SetApkAssets({style_assets_}); AssetManager2 am_night; - am_night.SetApkAssets({style_assets_.get()}); + am_night.SetApkAssets({style_assets_}); ResTable_config night{}; night.uiMode = ResTable_config::UI_MODE_NIGHT_YES; @@ -327,12 +326,11 @@ TEST_F(ThemeTest, ThemeRebase) { TEST_F(ThemeTest, OnlyCopySameAssetsThemeWhenAssetManagersDiffer) { AssetManager2 assetmanager_dst; - assetmanager_dst.SetApkAssets({system_assets_.get(), lib_one_assets_.get(), style_assets_.get(), - libclient_assets_.get()}); + assetmanager_dst.SetApkAssets( + {system_assets_, lib_one_assets_, style_assets_, libclient_assets_}); AssetManager2 assetmanager_src; - assetmanager_src.SetApkAssets({system_assets_.get(), lib_two_assets_.get(), lib_one_assets_.get(), - style_assets_.get()}); + assetmanager_src.SetApkAssets({system_assets_, lib_two_assets_, lib_one_assets_, style_assets_}); auto theme_dst = assetmanager_dst.NewTheme(); ASSERT_TRUE(theme_dst->ApplyStyle(app::R::style::StyleOne).has_value()); @@ -376,10 +374,10 @@ TEST_F(ThemeTest, OnlyCopySameAssetsThemeWhenAssetManagersDiffer) { TEST_F(ThemeTest, CopyNonReferencesWhenPackagesDiffer) { AssetManager2 assetmanager_dst; - assetmanager_dst.SetApkAssets({system_assets_.get()}); + assetmanager_dst.SetApkAssets({system_assets_}); AssetManager2 assetmanager_src; - assetmanager_src.SetApkAssets({system_assets_.get(), style_assets_.get()}); + assetmanager_src.SetApkAssets({system_assets_, style_assets_}); auto theme_dst = assetmanager_dst.NewTheme(); auto theme_src = assetmanager_src.NewTheme(); diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.kt b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.kt index 26efb55fa560..473603002b21 100644 --- a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.kt +++ b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.kt @@ -111,8 +111,14 @@ class LowLightTransitionCoordinator @Inject constructor() { } animator.addListener(listener) continuation.invokeOnCancellation { - animator.removeListener(listener) - animator.cancel() + try { + animator.removeListener(listener) + animator.cancel() + } catch (exception: IndexOutOfBoundsException) { + // TODO(b/285666217): remove this try/catch once a proper fix is implemented. + // Cancelling the animator can cause an exception since we may be removing a + // listener during the cancellation. See b/285666217 for more details. + } } } } diff --git a/libs/hwui/jni/BitmapRegionDecoder.cpp b/libs/hwui/jni/BitmapRegionDecoder.cpp index 4c9a23d3fde0..740988f77270 100644 --- a/libs/hwui/jni/BitmapRegionDecoder.cpp +++ b/libs/hwui/jni/BitmapRegionDecoder.cpp @@ -90,8 +90,8 @@ public: requireUnpremul, prefColorSpace); } - bool decodeGainmapRegion(sp<uirenderer::Gainmap>* outGainmap, const SkIRect& desiredSubset, - int sampleSize, bool requireUnpremul) { + bool decodeGainmapRegion(sp<uirenderer::Gainmap>* outGainmap, int outWidth, int outHeight, + const SkIRect& desiredSubset, int sampleSize, bool requireUnpremul) { SkColorType decodeColorType = mGainmapBRD->computeOutputColorType(kN32_SkColorType); sk_sp<SkColorSpace> decodeColorSpace = mGainmapBRD->computeOutputColorSpace(decodeColorType, nullptr); @@ -109,9 +109,8 @@ public: // kPremul_SkAlphaType is used just as a placeholder as it doesn't change the underlying // allocation type. RecyclingClippingPixelAllocator will populate this with the // actual alpha type in either allocPixelRef() or copyIfNecessary() - sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap( - SkImageInfo::Make(desiredSubset.width(), desiredSubset.height(), decodeColorType, - kPremul_SkAlphaType, decodeColorSpace)); + sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(SkImageInfo::Make( + outWidth, outHeight, decodeColorType, kPremul_SkAlphaType, decodeColorSpace)); if (!nativeBitmap) { ALOGE("OOM allocating Bitmap for Gainmap"); return false; @@ -134,9 +133,12 @@ public: return true; } - SkIRect calculateGainmapRegion(const SkIRect& mainImageRegion) { + SkIRect calculateGainmapRegion(const SkIRect& mainImageRegion, int* inOutWidth, + int* inOutHeight) { const float scaleX = ((float)mGainmapBRD->width()) / mMainImageBRD->width(); const float scaleY = ((float)mGainmapBRD->height()) / mMainImageBRD->height(); + *inOutWidth *= scaleX; + *inOutHeight *= scaleY; // TODO: Account for rounding error? return SkIRect::MakeLTRB(mainImageRegion.left() * scaleX, mainImageRegion.top() * scaleY, mainImageRegion.right() * scaleX, @@ -328,21 +330,16 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in sp<uirenderer::Gainmap> gainmap; bool hasGainmap = brd->hasGainmap(); if (hasGainmap) { - SkIRect adjustedSubset{}; + int gainmapWidth = bitmap.width(); + int gainmapHeight = bitmap.height(); if (javaBitmap) { - // Clamp to the width/height of the recycled bitmap in case the reused bitmap - // was too small for the specified rectangle, in which case we need to clip - adjustedSubset = SkIRect::MakeXYWH(inputX, inputY, - std::min(subset.width(), recycledBitmap->width()), - std::min(subset.height(), recycledBitmap->height())); - } else { - // We are not recycling, so use the decoded width/height for calculating the gainmap - // subset instead to ensure the gainmap region proportionally matches - adjustedSubset = SkIRect::MakeXYWH(std::max(0, inputX), std::max(0, inputY), - bitmap.width(), bitmap.height()); + // If we are recycling we must match the inBitmap's relative dimensions + gainmapWidth = recycledBitmap->width(); + gainmapHeight = recycledBitmap->height(); } - SkIRect gainmapSubset = brd->calculateGainmapRegion(adjustedSubset); - if (!brd->decodeGainmapRegion(&gainmap, gainmapSubset, sampleSize, requireUnpremul)) { + SkIRect gainmapSubset = brd->calculateGainmapRegion(subset, &gainmapWidth, &gainmapHeight); + if (!brd->decodeGainmapRegion(&gainmap, gainmapWidth, gainmapHeight, gainmapSubset, + sampleSize, requireUnpremul)) { // If there is an error decoding Gainmap - we don't fail. We just don't provide Gainmap hasGainmap = false; } diff --git a/libs/hwui/renderthread/HintSessionWrapper.cpp b/libs/hwui/renderthread/HintSessionWrapper.cpp index 814ac4d90028..30e472a79926 100644 --- a/libs/hwui/renderthread/HintSessionWrapper.cpp +++ b/libs/hwui/renderthread/HintSessionWrapper.cpp @@ -93,8 +93,13 @@ HintSessionWrapper::HintSessionWrapper(pid_t uiThreadId, pid_t renderThreadId) : mUiThreadId(uiThreadId), mRenderThreadId(renderThreadId) {} HintSessionWrapper::~HintSessionWrapper() { + if (mHintSessionFuture.valid()) { + mHintSession = mHintSessionFuture.get(); + } if (mHintSession) { gAPH_closeSessionFn(mHintSession); + mSessionValid = true; + mHintSession = nullptr; } } diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index d4e919fefbbd..46698a6fdcc0 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -40,7 +40,7 @@ namespace android { namespace uirenderer { namespace renderthread { -static std::array<std::string_view, 19> sEnableExtensions{ +static std::array<std::string_view, 20> sEnableExtensions{ VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, @@ -60,6 +60,7 @@ static std::array<std::string_view, 19> sEnableExtensions{ VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, + VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, }; static bool shouldEnableExtension(const std::string_view& extension) { @@ -657,7 +658,6 @@ void VulkanManager::destroySurface(VulkanSurface* surface) { if (VK_NULL_HANDLE != mGraphicsQueue) { mQueueWaitIdle(mGraphicsQueue); } - mDeviceWaitIdle(mDevice); delete surface; } |