diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-12-15 09:34:44 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-12-15 09:34:44 +0000 |
commit | 2695a9cf491f10d520ddb8ac958b67b0be5f7b31 (patch) | |
tree | 5b0230ca240cce33d45fbc4463c57f1ad458f84b | |
parent | 8df466a9db142b43a784cbe632a1cc69db643dfd (diff) | |
parent | 3cb1247941490e5c028b3feaf3c2b01ecdb8a8a4 (diff) | |
download | DocumentsUI-aml_tz5_341510010.tar.gz |
Snap for 11224086 from 3cb1247941490e5c028b3feaf3c2b01ecdb8a8a4 to mainline-tzdata5-releaseaml_tz5_341510070aml_tz5_341510050aml_tz5_341510010aml_tz5_341510010
Change-Id: Iba250c8aee749b798a435191a19d16c9fd6f6d07
48 files changed, 481 insertions, 189 deletions
diff --git a/app-perf-tests/Android.bp b/app-perf-tests/Android.bp index f753ac5b5..5a4bf72a4 100644 --- a/app-perf-tests/Android.bp +++ b/app-perf-tests/Android.bp @@ -20,7 +20,7 @@ android_test { "androidx.legacy_legacy-support-v4", "collector-device-lib", "mockito-target", - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", ], platform_apis: true, diff --git a/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java b/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java index 8366c89f5..821198dbd 100644 --- a/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java +++ b/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java @@ -32,9 +32,10 @@ import android.content.pm.ResolveInfo; import android.os.Bundle; import android.os.SystemClock; import android.provider.DocumentsContract; -import android.support.test.uiautomator.UiDevice; import android.util.Log; +import androidx.test.uiautomator.UiDevice; + import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/perf-tests/Android.bp b/perf-tests/Android.bp index 955b1c031..d98c36cf5 100644 --- a/perf-tests/Android.bp +++ b/perf-tests/Android.bp @@ -28,7 +28,7 @@ android_test { "androidx.test.espresso.core", "mockito-target", "ub-janktesthelper", - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", ], platform_apis: true, diff --git a/perf-tests/src/com/android/documentsui/FilesJankPerfTest.java b/perf-tests/src/com/android/documentsui/FilesJankPerfTest.java index 04dfc7882..6dd804443 100644 --- a/perf-tests/src/com/android/documentsui/FilesJankPerfTest.java +++ b/perf-tests/src/com/android/documentsui/FilesJankPerfTest.java @@ -16,27 +16,24 @@ package com.android.documentsui; -import static com.android.documentsui.StressProvider.DEFAULT_AUTHORITY; -import static com.android.documentsui.StressProvider.STRESS_ROOT_0_ID; import static com.android.documentsui.StressProvider.STRESS_ROOT_2_ID; import android.app.Activity; -import android.os.RemoteException; -import android.test.suitebuilder.annotation.LargeTest; - import android.app.UiAutomation; -import android.content.Intent; import android.content.Context; +import android.content.Intent; +import android.os.RemoteException; +import android.support.test.jank.GfxMonitor; import android.support.test.jank.JankTest; import android.support.test.jank.JankTestBase; -import android.support.test.uiautomator.UiDevice; -import android.support.test.jank.GfxMonitor; -import android.support.test.uiautomator.UiScrollable; -import android.util.Log; +import android.test.suitebuilder.annotation.LargeTest; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiScrollable; + +import com.android.documentsui.bots.DirectoryListBot; import com.android.documentsui.bots.SidebarBot; import com.android.documentsui.files.FilesActivity; -import com.android.documentsui.bots.DirectoryListBot; @LargeTest public class FilesJankPerfTest extends JankTestBase { diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index 32c9ff2d9..e68194b2e 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -27,7 +27,7 @@ <string name="title_open" msgid="3165686459158020921">"ክፈት ከ"</string> <string name="title_save" msgid="4384490653102710025">"አስቀምጥ ወደ"</string> <string name="menu_create_dir" msgid="2413624798689091042">"አዲስ አቃፊ"</string> - <string name="menu_grid" msgid="1453636521731880680">"የፍርግርግ እይታ"</string> + <string name="menu_grid" msgid="1453636521731880680">"የፍርግርግ ዕይታ"</string> <string name="menu_list" msgid="6714267452146410402">"የዝርዝር ዕይታ"</string> <string name="menu_search" msgid="1876699106790719849">"ፈልግ"</string> <string name="menu_settings" msgid="6520844520117939047">"የማከማቻ ቅንብሮች"</string> @@ -264,7 +264,7 @@ <string name="chip_title_from_this_week" msgid="4961536405220379672">"በዚህ ሳምንት"</string> <string name="input_hint_new_folder" msgid="479672411219725677">"የአቃፊ ስም"</string> <string name="input_hint_rename" msgid="8390711744270994452">"አዲስ ስም"</string> - <string name="preview_file" msgid="4056622696305432343">"<xliff:g id="FILENAME">%1$s</xliff:g> ፋይሉን በቅድመ እይታ ይመልከቱ"</string> + <string name="preview_file" msgid="4056622696305432343">"<xliff:g id="FILENAME">%1$s</xliff:g> ፋይሉን በቅድመ ዕይታ ይመልከቱ"</string> <string name="preview_work_file" msgid="4495643735563487273">"የሥራ ፋይሉን <xliff:g id="FILENAME">%1$s</xliff:g> በቅድመ ዕይታ አሳይ"</string> <string name="apps_row_title" msgid="3340490016663092925">"ፋይሎችን በሌሎች መተግበሪያዎች ውስጥ ያስሱ"</string> <string name="anonymous_application" msgid="7633027057951625862">"ስም-አልባ"</string> diff --git a/res/values-b+sr+Latn/inspector_strings.xml b/res/values-b+sr+Latn/inspector_strings.xml index 5bc9b8cb6..528cbd097 100644 --- a/res/values-b+sr+Latn/inspector_strings.xml +++ b/res/values-b+sr+Latn/inspector_strings.xml @@ -33,7 +33,7 @@ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string> <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string> <string name="metadata_aperture" msgid="6538741952698935357">"Otvor blende"</string> - <string name="metadata_shutter_speed" msgid="8204739885103326131">"Brzina okidača"</string> + <string name="metadata_shutter_speed" msgid="8204739885103326131">"Ekspozicija"</string> <string name="metadata_duration" msgid="3115494422055472715">"Trajanje"</string> <string name="metadata_date_time" msgid="1090351199248114406">"Snimljeno"</string> <string name="metadata_focal_length" msgid="3440735161407699893">"Žižna daljina"</string> diff --git a/res/values-eu/inspector_strings.xml b/res/values-eu/inspector_strings.xml index cf901d716..7e8f506cd 100644 --- a/res/values-eu/inspector_strings.xml +++ b/res/values-eu/inspector_strings.xml @@ -33,7 +33,7 @@ <string name="metadata_camera" msgid="2363009732801281319">"Kamera"</string> <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string> <string name="metadata_aperture" msgid="6538741952698935357">"Irekidura"</string> - <string name="metadata_shutter_speed" msgid="8204739885103326131">"Kliskagailuaren abiadura"</string> + <string name="metadata_shutter_speed" msgid="8204739885103326131">"Obturadorearen abiadura"</string> <string name="metadata_duration" msgid="3115494422055472715">"Iraupena"</string> <string name="metadata_date_time" msgid="1090351199248114406">"Data"</string> <string name="metadata_focal_length" msgid="3440735161407699893">"Foku-distantzia"</string> diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index d0961baa8..f40b13d14 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -77,8 +77,8 @@ <string name="sort_dimension_file_type_ascending" msgid="3466973933402894292">"نوع (بهترتیب حروف الفبا)"</string> <string name="sort_dimension_size_ascending" msgid="2617359017800057762">"اندازه (ابتدا کوچکترین)"</string> <string name="sort_dimension_date_ascending" msgid="7920068979386920559">"اصلاحشده (ابتدا قدیمیترین)"</string> - <string name="sort_dimension_name_descending" msgid="1514525521100423342">"نام فایل (Z تا A)"</string> - <string name="sort_dimension_file_type_descending" msgid="3344796059784511100">"نوع (Z تا A)"</string> + <string name="sort_dimension_name_descending" msgid="1514525521100423342">"نام فایل (ی تا الف)"</string> + <string name="sort_dimension_file_type_descending" msgid="3344796059784511100">"نوع (ی تا الف)"</string> <string name="sort_dimension_size_descending" msgid="2367030017597348938">"اندازه (ابتدا بزرگترین)"</string> <string name="sort_dimension_date_descending" msgid="5466839955763127113">"اصلاحشده (ابتدا جدیدترین)"</string> <string name="sort_dimension_dialog_title" msgid="3048641573962982157">"مرتب کردن براساس"</string> diff --git a/res/values-it/inspector_strings.xml b/res/values-it/inspector_strings.xml index a853094e3..7e81318db 100644 --- a/res/values-it/inspector_strings.xml +++ b/res/values-it/inspector_strings.xml @@ -33,7 +33,7 @@ <string name="metadata_camera" msgid="2363009732801281319">"Fotocamera"</string> <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string> <string name="metadata_aperture" msgid="6538741952698935357">"Apertura"</string> - <string name="metadata_shutter_speed" msgid="8204739885103326131">"Velocità otturatore"</string> + <string name="metadata_shutter_speed" msgid="8204739885103326131">"Tempo di esposizione"</string> <string name="metadata_duration" msgid="3115494422055472715">"Durata"</string> <string name="metadata_date_time" msgid="1090351199248114406">"Data/ora"</string> <string name="metadata_focal_length" msgid="3440735161407699893">"Lunghezza focale"</string> diff --git a/res/values-iw/inspector_strings.xml b/res/values-iw/inspector_strings.xml index 22543c9a5..2b62b162d 100644 --- a/res/values-iw/inspector_strings.xml +++ b/res/values-iw/inspector_strings.xml @@ -33,7 +33,7 @@ <string name="metadata_camera" msgid="2363009732801281319">"מצלמה"</string> <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string> <string name="metadata_aperture" msgid="6538741952698935357">"צמצם"</string> - <string name="metadata_shutter_speed" msgid="8204739885103326131">"מהירות תריס"</string> + <string name="metadata_shutter_speed" msgid="8204739885103326131">"מהירות התריס"</string> <string name="metadata_duration" msgid="3115494422055472715">"משך"</string> <string name="metadata_date_time" msgid="1090351199248114406">"תאריך צילום:"</string> <string name="metadata_focal_length" msgid="3440735161407699893">"אורך מוקד"</string> diff --git a/res/values-or/inspector_strings.xml b/res/values-or/inspector_strings.xml index dadb1540b..f0d68e17c 100644 --- a/res/values-or/inspector_strings.xml +++ b/res/values-or/inspector_strings.xml @@ -42,6 +42,6 @@ <string name="metadata_iso_format" msgid="4153285204012694861">"ISO <xliff:g id="ISO_SPEED">%1$d</xliff:g>"</string> <string name="metadata_artist" msgid="8972421485694988540">"କଳାକାର"</string> <string name="metadata_composer" msgid="4696926808308256056">"କମ୍ପୋଜର୍"</string> - <string name="metadata_album" msgid="1661699531214720236">"ଆଲବମ୍"</string> + <string name="metadata_album" msgid="1661699531214720236">"ଆଲବମ"</string> <string name="metadata_address" msgid="1849921023707744640">"ଲୋକେସନ"</string> </resources> diff --git a/res/values-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml index d751a55a1..96030ed1e 100644 --- a/res/values-pt-rBR/strings.xml +++ b/res/values-pt-rBR/strings.xml @@ -253,7 +253,7 @@ <string name="images_shortcut_label" msgid="2545168016070493574">"Imagens"</string> <string name="archive_loading_failed" msgid="7243436722828766996">"Não foi possível abrir o arquivo para navegação, pois ele está corrompido ou tem um formato incompatível."</string> <string name="name_conflict" msgid="28407269328862986">"Já existe um arquivo com esse nome."</string> - <string name="authentication_required" msgid="8030880723643436099">"Para ver esse diretório, faça login em <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="authentication_required" msgid="8030880723643436099">"Para acessar esse diretório, faça login em <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="cant_display_content" msgid="8633226333229417237">"Não é possível exibir conteúdos"</string> <string name="sign_in" msgid="6253762676723505592">"Fazer login"</string> <string name="new_archive_file_name" msgid="1604650338077249838">"arquivo<xliff:g id="EXTENSION">%s</xliff:g>"</string> diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 7a69fd6fd..9eb8f12c6 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -218,9 +218,9 @@ <string name="rename_error" msgid="6700093173508118635">"Falha ao mudar o nome do documento"</string> <string name="menu_eject_root" msgid="9215040039374893613">"Ejetar"</string> <string name="notification_copy_files_converted_title" msgid="6916768494891833365">"Alguns ficheiros foram convertidos"</string> - <string name="open_external_dialog_request" msgid="8173558471322861268">"Pretende conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no(a) <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string> - <string name="open_external_dialog_request_primary_volume" msgid="2240992164087948176">"Pretende conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string> - <string name="open_external_dialog_root_request" msgid="6776729293982633">"Pretende conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso aos seus dados, incluindo fotos e vídeos, no(a) <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string> + <string name="open_external_dialog_request" msgid="8173558471322861268">"Quer conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no(a) <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string> + <string name="open_external_dialog_request_primary_volume" msgid="2240992164087948176">"Quer conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string> + <string name="open_external_dialog_root_request" msgid="6776729293982633">"Quer conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso aos seus dados, incluindo fotos e vídeos, no(a) <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string> <string name="allow" msgid="1275746941353040309">"Permitir"</string> <string name="deny" msgid="5127201668078153379">"Recusar"</string> <plurals name="elements_selected" formatted="false" msgid="4448165978637163692"> @@ -257,7 +257,7 @@ <string name="cant_display_content" msgid="8633226333229417237">"Não é possível apresentar conteúdos"</string> <string name="sign_in" msgid="6253762676723505592">"Iniciar sessão"</string> <string name="new_archive_file_name" msgid="1604650338077249838">"arquivo<xliff:g id="EXTENSION">%s</xliff:g>"</string> - <string name="overwrite_file_confirmation_message" msgid="2496109652768222716">"Pretende substituir <xliff:g id="NAME">%1$s</xliff:g>?"</string> + <string name="overwrite_file_confirmation_message" msgid="2496109652768222716">"Quer substituir <xliff:g id="NAME">%1$s</xliff:g>?"</string> <string name="continue_in_background" msgid="1974214559047793331">"Continuar em segundo plano"</string> <plurals name="selected_count" formatted="false" msgid="7555250236512981129"> <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item> diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index d751a55a1..96030ed1e 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -253,7 +253,7 @@ <string name="images_shortcut_label" msgid="2545168016070493574">"Imagens"</string> <string name="archive_loading_failed" msgid="7243436722828766996">"Não foi possível abrir o arquivo para navegação, pois ele está corrompido ou tem um formato incompatível."</string> <string name="name_conflict" msgid="28407269328862986">"Já existe um arquivo com esse nome."</string> - <string name="authentication_required" msgid="8030880723643436099">"Para ver esse diretório, faça login em <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="authentication_required" msgid="8030880723643436099">"Para acessar esse diretório, faça login em <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="cant_display_content" msgid="8633226333229417237">"Não é possível exibir conteúdos"</string> <string name="sign_in" msgid="6253762676723505592">"Fazer login"</string> <string name="new_archive_file_name" msgid="1604650338077249838">"arquivo<xliff:g id="EXTENSION">%s</xliff:g>"</string> diff --git a/res/values-sk/inspector_strings.xml b/res/values-sk/inspector_strings.xml index de234a592..8b4634e42 100644 --- a/res/values-sk/inspector_strings.xml +++ b/res/values-sk/inspector_strings.xml @@ -33,7 +33,7 @@ <string name="metadata_camera" msgid="2363009732801281319">"Fotoaparát"</string> <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string> <string name="metadata_aperture" msgid="6538741952698935357">"Clona"</string> - <string name="metadata_shutter_speed" msgid="8204739885103326131">"Rýchlosť uzávierky"</string> + <string name="metadata_shutter_speed" msgid="8204739885103326131">"Expozičný čas"</string> <string name="metadata_duration" msgid="3115494422055472715">"Trvanie"</string> <string name="metadata_date_time" msgid="1090351199248114406">"Nasnímané"</string> <string name="metadata_focal_length" msgid="3440735161407699893">"Ohnisková vzdialenosť"</string> diff --git a/res/values-sq/inspector_strings.xml b/res/values-sq/inspector_strings.xml index 6d2bc1067..6c4166c2c 100644 --- a/res/values-sq/inspector_strings.xml +++ b/res/values-sq/inspector_strings.xml @@ -19,7 +19,7 @@ <string name="inspector_title" msgid="1924760928091740238">"Informacione"</string> <string name="inspector_load_error" msgid="7522190243413249291">"Informacioni i skedarit nuk mund të ngarkohej"</string> <string name="inspector_debug_section" msgid="2576052661505700421">"Informacioni i korrigjimit (vetëm zhvilluesit)"</string> - <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Të dhënat meta të papërpunuara: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string> + <string name="inspector_debug_metadata_section" msgid="5875140675600744846">"Metadatat e papërpunuara: <xliff:g id="METADATATYPE">%1$s</xliff:g>"</string> <string name="inspector_metadata_section" msgid="6077622515328240575">"Detajet e medias"</string> <string name="handler_app_file_opens_with" msgid="5272329600389613550">"Ky lloj skedari hapet me"</string> <string name="handler_app_belongs_to" msgid="5444507329303253553">"Ky skedar ofrohet nga"</string> diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index 96f01f23d..30d115d24 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -117,7 +117,7 @@ <string name="toast_failed_delete" msgid="3453846588205817591">"E pamundur të fshihen disa dokumente"</string> <string name="toast_share_over_limit" msgid="5805442886537093015">"Nuk mund të ndahen më shumë se <xliff:g id="COUNT">%1$d</xliff:g> skedarë"</string> <string name="toast_action_not_allowed" msgid="1329382474450572415">"Veprimi nuk lejohet"</string> - <string name="share_via" msgid="8725082736005677161">"Shpërndaj nëpërmjet"</string> + <string name="share_via" msgid="8725082736005677161">"Ndaj nëpërmjet"</string> <string name="copy_notification_title" msgid="52256435625098456">"Po kopjon skedarët"</string> <string name="compress_notification_title" msgid="6830195148113751021">"Skedarët po ngjishen"</string> <string name="extract_notification_title" msgid="5067393961754430469">"Po nxjerr skedarët"</string> diff --git a/res/values-sr/inspector_strings.xml b/res/values-sr/inspector_strings.xml index 8e4e6821a..2bf1962ba 100644 --- a/res/values-sr/inspector_strings.xml +++ b/res/values-sr/inspector_strings.xml @@ -33,7 +33,7 @@ <string name="metadata_camera" msgid="2363009732801281319">"Камера"</string> <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string> <string name="metadata_aperture" msgid="6538741952698935357">"Отвор бленде"</string> - <string name="metadata_shutter_speed" msgid="8204739885103326131">"Брзина окидача"</string> + <string name="metadata_shutter_speed" msgid="8204739885103326131">"Експозиција"</string> <string name="metadata_duration" msgid="3115494422055472715">"Трајање"</string> <string name="metadata_date_time" msgid="1090351199248114406">"Снимљено"</string> <string name="metadata_focal_length" msgid="3440735161407699893">"Жижна даљина"</string> diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index b238e78d0..5ec185c48 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -45,7 +45,7 @@ <string name="menu_move" msgid="2310760789561129882">"இங்கு நகர்த்து…"</string> <string name="menu_compress" msgid="37539111904724188">"அளவைக் குறை"</string> <string name="menu_extract" msgid="8171946945982532262">"இங்கு பிரி…"</string> - <string name="menu_rename" msgid="1883113442688817554">"மறுபெயரிடு"</string> + <string name="menu_rename" msgid="1883113442688817554">"பெயர் மாற்று"</string> <string name="menu_inspect" msgid="7279855349299446224">"தகவலைப் பெறு"</string> <string name="menu_show_hidden_files" msgid="5140676344684492769">"மறைக்கப்பட்ட ஃபைல்களைக் காட்டு"</string> <string name="menu_hide_hidden_files" msgid="5654495713350153702">"மறைக்கப்பட்ட ஃபைல்களைக் காட்டாதே"</string> diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 27db5ba14..b8879c828 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -33,7 +33,7 @@ <string name="menu_settings" msgid="6520844520117939047">"స్టోరేజ్ సెట్టింగ్లు"</string> <string name="menu_open" msgid="9092138100049759315">"తెరువు"</string> <string name="menu_open_with" msgid="5507647065467520229">"దీనితో తెరువు"</string> - <string name="menu_open_in_new_window" msgid="6686563636123311276">"కొత్త విండోలో తెరువు"</string> + <string name="menu_open_in_new_window" msgid="6686563636123311276">"కొత్త విండోలో తెరవండి"</string> <string name="menu_save" msgid="5195367497138965168">"సేవ్ చేయండి"</string> <string name="menu_share" msgid="4307140947108068356">"షేర్ చేయి"</string> <string name="menu_delete" msgid="1022254131543256626">"తొలగించండి"</string> diff --git a/res/values-vi/inspector_strings.xml b/res/values-vi/inspector_strings.xml index 568d3009c..048af2b39 100644 --- a/res/values-vi/inspector_strings.xml +++ b/res/values-vi/inspector_strings.xml @@ -33,7 +33,7 @@ <string name="metadata_camera" msgid="2363009732801281319">"Máy ảnh"</string> <string name="metadata_camera_format" msgid="1494489751904311612">"<xliff:g id="MAKE">%1$s</xliff:g> <xliff:g id="MODEL">%2$s</xliff:g>"</string> <string name="metadata_aperture" msgid="6538741952698935357">"Khẩu độ"</string> - <string name="metadata_shutter_speed" msgid="8204739885103326131">"Tốc độ chụp"</string> + <string name="metadata_shutter_speed" msgid="8204739885103326131">"Tốc độ màn trập"</string> <string name="metadata_duration" msgid="3115494422055472715">"Thời lượng"</string> <string name="metadata_date_time" msgid="1090351199248114406">"Chụp vào"</string> <string name="metadata_focal_length" msgid="3440735161407699893">"Tiêu cự"</string> diff --git a/src/com/android/documentsui/AbstractActionHandler.java b/src/com/android/documentsui/AbstractActionHandler.java index a310acee2..4407a62b2 100644 --- a/src/com/android/documentsui/AbstractActionHandler.java +++ b/src/com/android/documentsui/AbstractActionHandler.java @@ -779,32 +779,48 @@ public abstract class AbstractActionHandler<T extends FragmentActivity & CommonA } protected final boolean launchToDocument(Uri uri) { + if (DEBUG) { + Log.d(TAG, "launchToDocument() uri=" + uri); + } + // We don't support launching to a document in an archive. - if (!Providers.isArchiveUri(uri)) { - loadDocument(uri, UserId.DEFAULT_USER, this::onStackLoaded); - return true; + if (Providers.isArchiveUri(uri)) { + return false; } - return false; + loadDocument(uri, UserId.DEFAULT_USER, this::onStackToLaunchToLoaded); + return true; } - private void onStackLoaded(@Nullable DocumentStack stack) { - if (stack != null) { - if (!stack.peek().isDirectory()) { - // Requested document is not a directory. Pop it so that we can launch into its - // parent. - stack.pop(); - } - mState.stack.reset(stack); - mActivity.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE); + /** + * Invoked <b>only</b> once, when the initial stack (that is the stack we are going to + * "launch to") is loaded. + * + * @see #launchToDocument(Uri) + */ + private void onStackToLaunchToLoaded(@Nullable DocumentStack stack) { + if (DEBUG) { + Log.d(TAG, "onLaunchStackLoaded() stack=" + stack); + } - Metrics.logLaunchAtLocation(mState, stack.getRoot().getUri()); - } else { + if (stack == null) { Log.w(TAG, "Failed to launch into the given uri. Launch to default location."); launchToDefaultLocation(); Metrics.logLaunchAtLocation(mState, null); + return; } + + // Make sure the document at the top of the stack is a directory (if it isn't - just pop + // one off). + if (!stack.peek().isDirectory()) { + stack.pop(); + } + + mState.stack.reset(stack); + mActivity.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE); + + Metrics.logLaunchAtLocation(mState, stack.getRoot().getUri()); } private void onRootLoaded(@Nullable RootInfo root) { diff --git a/src/com/android/documentsui/picker/ActionHandler.java b/src/com/android/documentsui/picker/ActionHandler.java index cc349a854..1fc35b360 100644 --- a/src/com/android/documentsui/picker/ActionHandler.java +++ b/src/com/android/documentsui/picker/ActionHandler.java @@ -16,6 +16,9 @@ package com.android.documentsui.picker; +import static android.provider.DocumentsContract.isDocumentUri; +import static android.provider.DocumentsContract.isRootUri; + import static com.android.documentsui.base.SharedMinimal.DEBUG; import static com.android.documentsui.base.State.ACTION_CREATE; import static com.android.documentsui.base.State.ACTION_GET_CONTENT; @@ -23,6 +26,8 @@ import static com.android.documentsui.base.State.ACTION_OPEN; import static com.android.documentsui.base.State.ACTION_OPEN_TREE; import static com.android.documentsui.base.State.ACTION_PICK_COPY_DESTINATION; +import static java.util.regex.Pattern.CASE_INSENSITIVE; + import android.content.ActivityNotFoundException; import android.content.ClipData; import android.content.ComponentName; @@ -35,6 +40,8 @@ import android.provider.DocumentsContract; import android.provider.Settings; import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; @@ -52,6 +59,7 @@ import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.DocumentStack; import com.android.documentsui.base.Features; import com.android.documentsui.base.Lookup; +import com.android.documentsui.base.Providers; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.Shared; import com.android.documentsui.base.State; @@ -61,14 +69,12 @@ import com.android.documentsui.picker.ActionHandler.Addons; import com.android.documentsui.queries.SearchViewManager; import com.android.documentsui.roots.ProvidersAccess; import com.android.documentsui.services.FileOperationService; +import com.android.documentsui.util.FileUtils; -import com.android.documentsui.util.VersionUtils; +import java.io.IOException; import java.util.Arrays; -import java.util.Locale; import java.util.concurrent.Executor; - import java.util.regex.Pattern; -import javax.annotation.Nullable; /** * Provides {@link PickActivity} action specializations to fragments. @@ -77,12 +83,24 @@ class ActionHandler<T extends FragmentActivity & Addons> extends AbstractActionH private static final String TAG = "PickerActionHandler"; + /** + * Used to prevent applications from using {@link Intent.ACTION_OPEN_DOCUMENT_TREE} and + * the {@link Intent.ACTION_OPEN_DOCUMENT} actions to request that the user select individual + * files from "/Android/data", "/Android/obb", "/Android/sandbox" directories and all their + * subdirectories (on the external storage), in accordance with the SAF privacy restrictions + * introduced in Android 11 (R). + * + * <p> + * See <a href="https://developer.android.com/about/versions/11/privacy/storage#file-access"> + * Storage updates in Android 11</a>. + */ + private static final Pattern PATTERN_RESTRICTED_INITIAL_PATH = + Pattern.compile("^/Android/(?:data|obb|sandbox).*", CASE_INSENSITIVE); + private final Features mFeatures; private final ActivityConfig mConfig; private final LastAccessedStorage mLastAccessed; private final UserIdManager mUserIdManager; - private final static Pattern PATTERN_BLOCK_PATH = Pattern.compile( - ".*:android\\/(?:data|obb|sandbox)$"); private UpdatePickResultTask mUpdatePickResultTask; @@ -160,25 +178,84 @@ class ActionHandler<T extends FragmentActivity & Addons> extends AbstractActionH } private boolean launchToInitialUri(Intent intent) { - Uri uri = intent.getParcelableExtra(DocumentsContract.EXTRA_INITIAL_URI); - if (uri != null) { - // In android S and above if path contains Android/data, Android/obb - // or Android/sandbox redirect to the root for which - // FLAG_DIR_BLOCKS_OPEN_DOCUMENT_TREE is already set - if(Shared.shouldRestrictStorageAccessFramework(mActivity) - && (PATTERN_BLOCK_PATH.matcher(uri.getPath().toLowerCase(Locale.ROOT)).matches())){ - loadDeviceRoot(); - return true; - } - if (DocumentsContract.isRootUri(mActivity, uri)) { - loadRoot(uri, UserId.DEFAULT_USER); - return true; - } else if (DocumentsContract.isDocumentUri(mActivity, uri)) { - return launchToDocument(uri); - } + final Uri initialUri = intent.getParcelableExtra(DocumentsContract.EXTRA_INITIAL_URI); + if (initialUri == null) { + return false; } - return false; + final boolean isRoot = isRootUri(mActivity, initialUri); + final boolean isDocument = !isRoot && isDocumentUri(mActivity, initialUri); + + if (!isRoot && !isDocument) { + // Neither a root nor a document. + return false; + } + + if (isRoot) { + loadRoot(initialUri, UserId.DEFAULT_USER); + return true; + } + // From here onwards: isDoc == true. + + if (shouldPreemptivelyRestrictRequestedInitialUri(initialUri)) { + Log.w(TAG, "Requested initial URI - " + initialUri + " - is restricted: " + + "loading device root instead."); + return false; + } + + return launchToDocument(initialUri); + } + + /** + * Starting with Android 11 (R, API Level 30) applications are no longer allowed to use the + * {@link Intent#ACTION_OPEN_DOCUMENT} and {@link Intent#ACTION_OPEN_DOCUMENT_TREE} to request + * that the user select individual files from "Android/data/", "Android/obb/", + * "Android/sandbox/" directories and all their subdirectories on "external storage". + * <p> + * See <a href="https://developer.android.com/about/versions/11/privacy/storage#file-access"> + * Storage updates in Android 11</a>. + * <p> + * Ideally, this should be handled on the {@code ExternalStorageProvider} side, but as of + * Android 14 (U) FRC, {@code ExternalStorageProvider} "hides" only "Android/data/", + * "Android/obb/" and "Android/sandbox/" directories, but NOT their subdirectories. + */ + private boolean shouldPreemptivelyRestrictRequestedInitialUri(@NonNull Uri uri) { + // Not restricting SAF access for the calling app. + if (!Shared.shouldRestrictStorageAccessFramework(mActivity)) { + return false; + } + + // We only need to restrict some locations on the "external" storage. + if (!Providers.AUTHORITY_STORAGE.equals(uri.getAuthority())) { + return false; + } + + // TODO(b/283962634): in the future this will have to be platform-version specific. + // For example, if the fix on the ExternalStorageProvider side makes it to the Android 15, + // we would change this to check if the platform version >= 15. + // In the upcoming Android 14 release, however, ExternalStorageProvider does NOT yet + // implement this logic. + final boolean externalProviderImplementsSafRestrictions = false; + if (externalProviderImplementsSafRestrictions) { + return false; + } + + // External Storage Provider's docId format is "root:path/to/file" + // The getPathFromStorageDocId() turns that into "/path/to/file" + // Note the missing leading "/" in the path part of the docId, while the path returned by + // the getPathFromStorageDocId() start with "/". + final String docId = DocumentsContract.getDocumentId(uri); + final String filePath; + try { + filePath = FileUtils.getPathFromStorageDocId(docId); + } catch (IOException e) { + Log.w(TAG, "Could not get canonical file path from docId '" + docId + "'"); + return true; + } + + // Check if the app is asking for /Android/data, /Android/obb, /Android/sandbox or any of + // their subdirectories (on the external storage). + return PATTERN_RESTRICTED_INITIAL_PATH.matcher(filePath).matches(); } private void initLoadLastAccessedStack() { diff --git a/src/com/android/documentsui/queries/SearchFragment.java b/src/com/android/documentsui/queries/SearchFragment.java index 92cd91a3f..890d2b262 100644 --- a/src/com/android/documentsui/queries/SearchFragment.java +++ b/src/com/android/documentsui/queries/SearchFragment.java @@ -163,9 +163,9 @@ public class SearchFragment extends Fragment { updateDirectoryVisibility(View.VISIBLE); - FragmentTransaction ft = getParentFragmentManager().beginTransaction(); - ft.remove(this); - ft.commitNow(); + getParentFragmentManager().beginTransaction() + .remove(this) + .commitAllowingStateLoss(); } private void updateDirectoryVisibility(int visibility) { diff --git a/src/com/android/documentsui/util/FileUtils.java b/src/com/android/documentsui/util/FileUtils.java new file mode 100644 index 000000000..40f7fbae9 --- /dev/null +++ b/src/com/android/documentsui/util/FileUtils.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.documentsui.util; + +import androidx.annotation.NonNull; + +import java.io.File; +import java.io.IOException; +import java.util.Objects; + +public class FileUtils { + + /** + * Returns the canonical pathname string of the provided abstract pathname. + * + * @return The canonical pathname string denoting the same file or directory as this abstract + * pathname. + * @see File#getCanonicalPath() + */ + @NonNull + public static String getCanonicalPath(@NonNull String path) throws IOException { + Objects.requireNonNull(path); + return new File(path).getCanonicalPath(); + } + + /** + * This is basically a very slightly tweaked fork of + * {@link com.android.externalstorage.ExternalStorageProvider#getPathFromDocId(String)}. + * The difference between this fork and the "original" method is that here we do not strip + * the leading and trailing "/"s (because we don't worry about those). + * + * @return canonicalized file path. + */ + public static String getPathFromStorageDocId(String docId) throws IOException { + // Remove the root tag from the docId, e.g. "primary:", which should leave with the file + // path. + final String docIdPath = docId.substring(docId.indexOf(':', 1) + 1); + + return getCanonicalPath(docIdPath); + } + + private FileUtils() { + } +} diff --git a/tests/Android.bp b/tests/Android.bp index 7a5d63112..65a4bbdbd 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -95,7 +95,7 @@ android_test { "androidx.test.ext.truth", "guava", "mockito-target", - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", ], jarjar_rules: "jarjar-rules.txt", diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml index 7874118db..c5a00a2ea 100644 --- a/tests/AndroidTest.xml +++ b/tests/AndroidTest.xml @@ -18,6 +18,14 @@ <option name="test-file-name" value="DocumentsUITests.apk" /> </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> + <!-- Disable keyguard --> + <!-- Though keyguard is disabled globally in cts-preconditions.xml, this will ensure that + the test gets the same treatment when running in other test suites (e.g. MTS), as well + as when running locally (e.g. via atest) --> + <option name="run-command" value="locksettings set-disabled true" /> + </target_preparer> + <option name="test-suite-tag" value="apct" /> <option name="test-tag" value="DocumentsUITests" /> <test class="com.android.tradefed.testtype.AndroidJUnitTest" > diff --git a/tests/common/com/android/documentsui/TestActivity.java b/tests/common/com/android/documentsui/TestActivity.java index 2506bdf96..eb321fac0 100644 --- a/tests/common/com/android/documentsui/TestActivity.java +++ b/tests/common/com/android/documentsui/TestActivity.java @@ -263,6 +263,17 @@ public abstract class TestActivity extends AbstractBase { public final void finish() { finishedHandler.accept(null); } + + @Override + public boolean isInMultiWindowMode() { + // We are seeing this causing NPEs on older platform versions of some OEM, e.g. b/297710004. + // Hence we'll wrap this in a try-catch. + try { + return super.isInMultiWindowMode(); + } catch (Exception e) { + return false; + } + } } // Trick Mockito into finding our Addons methods correctly. W/o this diff --git a/tests/common/com/android/documentsui/bots/Bots.java b/tests/common/com/android/documentsui/bots/Bots.java index 8a3d347ec..8cc00ac7a 100644 --- a/tests/common/com/android/documentsui/bots/Bots.java +++ b/tests/common/com/android/documentsui/bots/Bots.java @@ -20,15 +20,15 @@ import static junit.framework.Assert.assertNotNull; import android.app.UiAutomation; import android.content.Context; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.BySelector; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiObject2; -import android.support.test.uiautomator.UiSelector; -import android.support.test.uiautomator.Until; import androidx.test.InstrumentationRegistry; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObject2; +import androidx.test.uiautomator.UiSelector; +import androidx.test.uiautomator.Until; /** * Handy collection of bots for working with Files app. diff --git a/tests/common/com/android/documentsui/bots/BreadBot.java b/tests/common/com/android/documentsui/bots/BreadBot.java index d022f52f2..7c1a81b3a 100644 --- a/tests/common/com/android/documentsui/bots/BreadBot.java +++ b/tests/common/com/android/documentsui/bots/BreadBot.java @@ -17,9 +17,10 @@ package com.android.documentsui.bots; import android.content.Context; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; + +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import junit.framework.Assert; diff --git a/tests/common/com/android/documentsui/bots/DirectoryListBot.java b/tests/common/com/android/documentsui/bots/DirectoryListBot.java index 9fbc39f2a..3e9fa30b8 100644 --- a/tests/common/com/android/documentsui/bots/DirectoryListBot.java +++ b/tests/common/com/android/documentsui/bots/DirectoryListBot.java @@ -27,21 +27,22 @@ import android.content.Context; import android.graphics.Point; import android.graphics.Rect; import android.os.SystemClock; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.BySelector; -import android.support.test.uiautomator.Configurator; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiObject2; -import android.support.test.uiautomator.UiObjectNotFoundException; -import android.support.test.uiautomator.UiScrollable; -import android.support.test.uiautomator.UiSelector; -import android.support.test.uiautomator.Until; import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.Configurator; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObject2; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiScrollable; +import androidx.test.uiautomator.UiSelector; +import androidx.test.uiautomator.Until; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/tests/common/com/android/documentsui/bots/GestureBot.java b/tests/common/com/android/documentsui/bots/GestureBot.java index 9a0fb6ea1..4c7f7c7c9 100644 --- a/tests/common/com/android/documentsui/bots/GestureBot.java +++ b/tests/common/com/android/documentsui/bots/GestureBot.java @@ -21,16 +21,17 @@ import android.content.Context; import android.graphics.Point; import android.graphics.Rect; import android.os.SystemClock; -import android.support.test.uiautomator.Configurator; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiObjectNotFoundException; -import android.support.test.uiautomator.UiSelector; import android.view.InputDevice; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; import android.view.MotionEvent.PointerProperties; +import androidx.test.uiautomator.Configurator; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiSelector; + /** * A test helper class that provides support for controlling directory list * and making assertions against the state of it. diff --git a/tests/common/com/android/documentsui/bots/InspectorBot.java b/tests/common/com/android/documentsui/bots/InspectorBot.java index 252fde452..7e459db04 100644 --- a/tests/common/com/android/documentsui/bots/InspectorBot.java +++ b/tests/common/com/android/documentsui/bots/InspectorBot.java @@ -20,12 +20,13 @@ import static junit.framework.Assert.assertTrue; import android.app.Activity; import android.content.Context; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiSelector; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiSelector; + import com.android.documentsui.R; import com.android.documentsui.inspector.DetailsView; import com.android.documentsui.inspector.KeyValueRow; diff --git a/tests/common/com/android/documentsui/bots/KeyboardBot.java b/tests/common/com/android/documentsui/bots/KeyboardBot.java index 6167acfc0..7cd3eedef 100644 --- a/tests/common/com/android/documentsui/bots/KeyboardBot.java +++ b/tests/common/com/android/documentsui/bots/KeyboardBot.java @@ -21,10 +21,11 @@ import static androidx.test.espresso.action.ViewActions.pressImeActionButton; import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; import android.content.Context; -import android.support.test.uiautomator.UiDevice; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; +import androidx.test.uiautomator.UiDevice; + /** * A test helper class that provides support for keyboard manipulation. */ diff --git a/tests/common/com/android/documentsui/bots/MenuBot.java b/tests/common/com/android/documentsui/bots/MenuBot.java index 511c51e4a..58e82e44c 100644 --- a/tests/common/com/android/documentsui/bots/MenuBot.java +++ b/tests/common/com/android/documentsui/bots/MenuBot.java @@ -16,13 +16,14 @@ package com.android.documentsui.bots; -import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; import android.content.Context; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObjectNotFoundException; + +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObjectNotFoundException; import java.util.Map; diff --git a/tests/common/com/android/documentsui/bots/NotificationsBot.java b/tests/common/com/android/documentsui/bots/NotificationsBot.java index 5ab872df5..5200ddb06 100644 --- a/tests/common/com/android/documentsui/bots/NotificationsBot.java +++ b/tests/common/com/android/documentsui/bots/NotificationsBot.java @@ -19,9 +19,9 @@ package com.android.documentsui.bots; import android.app.Activity; import android.content.ComponentName; import android.content.Context; -import android.support.test.uiautomator.UiDevice; import androidx.test.InstrumentationRegistry; +import androidx.test.uiautomator.UiDevice; import com.android.documentsui.services.TestNotificationService; diff --git a/tests/common/com/android/documentsui/bots/SearchBot.java b/tests/common/com/android/documentsui/bots/SearchBot.java index d14fd1375..51f93943a 100644 --- a/tests/common/com/android/documentsui/bots/SearchBot.java +++ b/tests/common/com/android/documentsui/bots/SearchBot.java @@ -31,13 +31,13 @@ import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.anyOf; import android.content.Context; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiObjectNotFoundException; -import android.support.test.uiautomator.UiSelector; import android.view.View; import androidx.recyclerview.R; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiSelector; import org.hamcrest.Matcher; diff --git a/tests/common/com/android/documentsui/bots/SidebarBot.java b/tests/common/com/android/documentsui/bots/SidebarBot.java index 4e961260d..01f311a7f 100644 --- a/tests/common/com/android/documentsui/bots/SidebarBot.java +++ b/tests/common/com/android/documentsui/bots/SidebarBot.java @@ -22,14 +22,15 @@ import static androidx.test.espresso.action.ViewActions.swipeRight; import static androidx.test.espresso.matcher.ViewMatchers.withId; import android.content.Context; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiObjectNotFoundException; -import android.support.test.uiautomator.UiScrollable; -import android.support.test.uiautomator.UiSelector; import android.util.Log; import android.view.View; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiScrollable; +import androidx.test.uiautomator.UiSelector; + import com.android.documentsui.R; import junit.framework.Assert; diff --git a/tests/common/com/android/documentsui/bots/SortBot.java b/tests/common/com/android/documentsui/bots/SortBot.java index 6b6f81788..74493ca66 100644 --- a/tests/common/com/android/documentsui/bots/SortBot.java +++ b/tests/common/com/android/documentsui/bots/SortBot.java @@ -33,12 +33,12 @@ import static junit.framework.Assert.assertTrue; import static org.hamcrest.Matchers.allOf; import android.content.Context; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; import android.view.View; import androidx.annotation.StringRes; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import com.android.documentsui.R; import com.android.documentsui.sorting.SortDimension; diff --git a/tests/common/com/android/documentsui/bots/UiBot.java b/tests/common/com/android/documentsui/bots/UiBot.java index 36256ff74..f30cb93b8 100644 --- a/tests/common/com/android/documentsui/bots/UiBot.java +++ b/tests/common/com/android/documentsui/bots/UiBot.java @@ -35,13 +35,6 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.endsWith; import android.content.Context; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiObject2; -import android.support.test.uiautomator.UiObjectNotFoundException; -import android.support.test.uiautomator.UiSelector; -import android.support.test.uiautomator.Until; import android.util.TypedValue; import android.view.View; @@ -51,6 +44,13 @@ import androidx.test.espresso.Espresso; import androidx.test.espresso.action.ViewActions; import androidx.test.espresso.matcher.BoundedMatcher; import androidx.test.espresso.matcher.ViewMatchers; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObject2; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiSelector; +import androidx.test.uiautomator.Until; import com.android.documentsui.R; diff --git a/tests/functional/com/android/documentsui/ActionCreateDocumentUiTest.java b/tests/functional/com/android/documentsui/ActionCreateDocumentUiTest.java index 1a355b90a..6939e3d0f 100644 --- a/tests/functional/com/android/documentsui/ActionCreateDocumentUiTest.java +++ b/tests/functional/com/android/documentsui/ActionCreateDocumentUiTest.java @@ -16,28 +16,30 @@ package com.android.documentsui; -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static android.app.Activity.RESULT_OK; +import static android.content.Intent.ACTION_CREATE_DOCUMENT; +import static android.content.Intent.CATEGORY_DEFAULT; +import static android.content.Intent.CATEGORY_OPENABLE; +import static android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION; +import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION; +import static android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION; import static com.android.documentsui.base.Providers.AUTHORITY_STORAGE; import static com.google.common.truth.Truth.assertThat; -import android.app.Activity; import android.app.Instrumentation; -import android.app.UiAutomation; -import android.content.Context; import android.content.Intent; import android.net.Uri; import android.provider.DocumentsContract; -import android.support.test.uiautomator.UiDevice; import androidx.test.filters.LargeTest; import androidx.test.rule.ActivityTestRule; import androidx.test.runner.AndroidJUnit4; -import com.android.documentsui.bots.Bots; import com.android.documentsui.picker.PickActivity; +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -48,62 +50,54 @@ import java.util.UUID; @LargeTest @RunWith(AndroidJUnit4.class) -public class ActionCreateDocumentUiTest { +public class ActionCreateDocumentUiTest extends DocumentsUiTestBase { @Rule public final ActivityTestRule<PickActivity> mRule = new ActivityTestRule<>(PickActivity.class, false, false); - private Context mTargetContext; - private Context mContext; - private Bots mBots; - private UiDevice mDevice; - @Before - public void setup() { - UiAutomation automation = getInstrumentation().getUiAutomation(); + public void setup() throws Exception { + super.setUp(); + } - mDevice = UiDevice.getInstance(getInstrumentation()); - mTargetContext = getInstrumentation().getTargetContext(); - mContext = getInstrumentation().getContext(); - mBots = new Bots(mDevice, automation, mTargetContext, 5000); + @After + public void tearDown() throws Exception { + super.tearDown(); } @Test public void testActionCreate_TextFile() throws Exception { - Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); - intent.addCategory(Intent.CATEGORY_DEFAULT); - intent.addCategory(Intent.CATEGORY_OPENABLE); + final Intent intent = new Intent(ACTION_CREATE_DOCUMENT); + intent.addCategory(CATEGORY_DEFAULT); + intent.addCategory(CATEGORY_OPENABLE); intent.setType("*/*"); - - Uri hintUri = DocumentsContract.buildRootUri(AUTHORITY_STORAGE, "primary"); - intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, hintUri); + intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, + DocumentsContract.buildRootUri(AUTHORITY_STORAGE, "primary")); mRule.launchActivity(intent); - String fileName = UUID.randomUUID().toString() + ".txt"; + final String fileName = UUID.randomUUID() + ".txt"; - mBots.main.setDialogText(fileName); - mBots.main.clickSaveButton(); - mDevice.waitForIdle(); + bots.main.setDialogText(fileName); + bots.main.clickSaveButton(); + device.waitForIdle(); - Instrumentation.ActivityResult activityResult = mRule.getActivityResult(); + final Instrumentation.ActivityResult activityResult = mRule.getActivityResult(); + assertThat(activityResult.getResultCode()).isEqualTo(RESULT_OK); - Intent result = activityResult.getResultData(); - Uri uri = result.getData(); - int flags = result.getFlags(); + final Intent resultData = activityResult.getResultData(); + final Uri uri = resultData.getData(); - assertThat(activityResult.getResultCode()).isEqualTo(Activity.RESULT_OK); assertThat(uri.getAuthority()).isEqualTo(AUTHORITY_STORAGE); assertThat(uri.getPath()).contains(fileName); - int expectedFlags = - Intent.FLAG_GRANT_READ_URI_PERMISSION - | Intent.FLAG_GRANT_WRITE_URI_PERMISSION - | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION; + assertThat(resultData.getFlags()).isEqualTo(FLAG_GRANT_READ_URI_PERMISSION + | FLAG_GRANT_WRITE_URI_PERMISSION + | FLAG_GRANT_PERSISTABLE_URI_PERMISSION); - assertThat(flags).isEqualTo(expectedFlags); - assertThat(DocumentsContract.deleteDocument(mContext.getContentResolver(), uri)).isTrue(); + final boolean deletedSuccessfully = + DocumentsContract.deleteDocument(context.getContentResolver(), uri); + assertThat(deletedSuccessfully).isTrue(); } - }
\ No newline at end of file diff --git a/tests/functional/com/android/documentsui/ActivityTest.java b/tests/functional/com/android/documentsui/ActivityTest.java index ec4e6cbea..bda672b79 100644 --- a/tests/functional/com/android/documentsui/ActivityTest.java +++ b/tests/functional/com/android/documentsui/ActivityTest.java @@ -16,6 +16,8 @@ package com.android.documentsui; +import static java.util.Objects.requireNonNull; + import android.app.Activity; import android.app.UiAutomation; import android.app.UiModeManager; @@ -28,19 +30,22 @@ import android.os.Bundle; import android.os.RemoteException; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Document; -import android.support.test.uiautomator.Configurator; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObjectNotFoundException; import android.test.ActivityInstrumentationTestCase2; import android.view.KeyEvent; import android.view.MotionEvent; +import androidx.test.uiautomator.Configurator; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObjectNotFoundException; + import com.android.documentsui.base.Features; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.UserId; import com.android.documentsui.bots.Bots; import com.android.documentsui.files.FilesActivity; +import java.io.IOException; + import javax.annotation.Nullable; /** @@ -77,6 +82,9 @@ public abstract class ActivityTest<T extends Activity> extends ActivityInstrumen protected ContentProviderClient mClient; protected UiModeManager mUiModeManager; + private String initialScreenOffTimeoutValue = null; + private String initialSleepTimeoutValue = null; + public ActivityTest(Class<T> activityClass) { super(activityClass); } @@ -128,6 +136,9 @@ public abstract class ActivityTest<T extends Activity> extends ActivityInstrumen device.setOrientationNatural(); device.pressKeyCode(KeyEvent.KEYCODE_WAKEUP); device.pressKeyCode(KeyEvent.KEYCODE_MENU); + + disableScreenOffAndSleepTimeouts(); + setupTestingRoots(); launchActivity(); @@ -147,6 +158,7 @@ public abstract class ActivityTest<T extends Activity> extends ActivityInstrumen public void tearDown() throws Exception { device.unfreezeRotation(); mDocsHelper.cleanUp(); + restoreScreenOffAndSleepTimeouts(); super.tearDown(); } @@ -210,4 +222,27 @@ public abstract class ActivityTest<T extends Activity> extends ActivityInstrumen device.waitForIdle(NIGHT_MODE_CHANGE_WAIT_TIME); } } + + private void disableScreenOffAndSleepTimeouts() throws IOException { + initialScreenOffTimeoutValue = device.executeShellCommand( + "settings get system screen_off_timeout"); + initialSleepTimeoutValue = device.executeShellCommand( + "settings get secure sleep_timeout"); + device.executeShellCommand("settings put system screen_off_timeout -1"); + device.executeShellCommand("settings put secure sleep_timeout -1"); + } + + private void restoreScreenOffAndSleepTimeouts() throws IOException { + requireNonNull(initialScreenOffTimeoutValue); + requireNonNull(initialSleepTimeoutValue); + try { + device.executeShellCommand( + "settings put system screen_off_timeout " + initialScreenOffTimeoutValue); + device.executeShellCommand( + "settings put secure sleep_timeout " + initialSleepTimeoutValue); + } finally { + initialScreenOffTimeoutValue = null; + initialSleepTimeoutValue = null; + } + } } diff --git a/tests/functional/com/android/documentsui/DialogUiTest.java b/tests/functional/com/android/documentsui/DialogUiTest.java index c9c9a7731..eec7ef15f 100644 --- a/tests/functional/com/android/documentsui/DialogUiTest.java +++ b/tests/functional/com/android/documentsui/DialogUiTest.java @@ -29,7 +29,6 @@ import android.content.pm.ActivityInfo; import android.graphics.Paint; import android.os.Build; import android.os.ParcelFileDescriptor; -import android.support.test.uiautomator.UiDevice; import android.view.KeyEvent; import androidx.fragment.app.FragmentManager; @@ -37,6 +36,7 @@ import androidx.test.filters.LargeTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; import androidx.test.runner.AndroidJUnit4; +import androidx.test.uiautomator.UiDevice; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.dirlist.RenameDocumentFragment; diff --git a/tests/functional/com/android/documentsui/DocumentsUiTestBase.java b/tests/functional/com/android/documentsui/DocumentsUiTestBase.java new file mode 100644 index 000000000..75e03bcb1 --- /dev/null +++ b/tests/functional/com/android/documentsui/DocumentsUiTestBase.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.documentsui; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static java.util.Objects.requireNonNull; + +import android.app.Instrumentation; +import android.content.Context; +import android.view.KeyEvent; + +import androidx.test.uiautomator.UiDevice; + +import com.android.documentsui.bots.Bots; + +import java.io.IOException; + + +/** Base class for instrumentation tests for DocumentsUI Activities. */ +class DocumentsUiTestBase { + private static final int BOTS_TIMEOUT = 5000; // 5 seconds + + protected Context targetContext; + protected Context context; + protected UiDevice device; + protected Bots bots; + + private String initialScreenOffTimeoutValue = null; + private String initialSleepTimeoutValue = null; + + protected void setUp() throws Exception { + final Instrumentation instrumentation = getInstrumentation(); + targetContext = instrumentation.getTargetContext(); + context = instrumentation.getContext(); + device = UiDevice.getInstance(instrumentation); + + disableScreenOffAndSleepTimeouts(); + + device.setOrientationNatural(); + + // "Wake-up" the device and navigate to the home page. + device.pressKeyCode(KeyEvent.KEYCODE_WAKEUP); + device.pressKeyCode(KeyEvent.KEYCODE_MENU); + + bots = new Bots(device, instrumentation.getUiAutomation(), targetContext, BOTS_TIMEOUT); + } + + protected void tearDown() throws Exception { + restoreScreenOffAndSleepTimeouts(); + } + + private void disableScreenOffAndSleepTimeouts() throws IOException { + initialScreenOffTimeoutValue = device.executeShellCommand( + "settings get system screen_off_timeout"); + initialSleepTimeoutValue = device.executeShellCommand( + "settings get secure sleep_timeout"); + device.executeShellCommand("settings put system screen_off_timeout -1"); + device.executeShellCommand("settings put secure sleep_timeout -1"); + } + + private void restoreScreenOffAndSleepTimeouts() throws IOException { + requireNonNull(initialScreenOffTimeoutValue); + requireNonNull(initialSleepTimeoutValue); + try { + device.executeShellCommand( + "settings put system screen_off_timeout " + initialScreenOffTimeoutValue); + device.executeShellCommand( + "settings put secure sleep_timeout " + initialSleepTimeoutValue); + } finally { + initialScreenOffTimeoutValue = null; + initialSleepTimeoutValue = null; + } + } +} diff --git a/tests/functional/com/android/documentsui/FileCopyUiTest.java b/tests/functional/com/android/documentsui/FileCopyUiTest.java index eba480924..1f3586820 100644 --- a/tests/functional/com/android/documentsui/FileCopyUiTest.java +++ b/tests/functional/com/android/documentsui/FileCopyUiTest.java @@ -33,11 +33,11 @@ import android.os.RemoteException; import android.os.SystemClock; import android.provider.MediaStore; import android.provider.Settings; -import android.support.test.uiautomator.UiObjectNotFoundException; import android.text.TextUtils; import android.util.Log; import androidx.test.filters.LargeTest; +import androidx.test.uiautomator.UiObjectNotFoundException; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.RootInfo; diff --git a/tests/functional/com/android/documentsui/IntegratedDownloadsUiTest.java b/tests/functional/com/android/documentsui/IntegratedDownloadsUiTest.java index 9302e52aa..aa55be9d2 100644 --- a/tests/functional/com/android/documentsui/IntegratedDownloadsUiTest.java +++ b/tests/functional/com/android/documentsui/IntegratedDownloadsUiTest.java @@ -20,12 +20,12 @@ import android.app.DownloadManager; import android.app.DownloadManager.Request; import android.content.Context; import android.net.Uri; -import android.support.test.uiautomator.Configurator; -import android.support.test.uiautomator.UiObject; import android.view.MotionEvent; import androidx.test.filters.LargeTest; import androidx.test.filters.Suppress; +import androidx.test.uiautomator.Configurator; +import androidx.test.uiautomator.UiObject; import com.android.documentsui.files.FilesActivity; diff --git a/tests/functional/com/android/documentsui/RenameDocumentUiTest.java b/tests/functional/com/android/documentsui/RenameDocumentUiTest.java index 585df5e74..e992ac95f 100644 --- a/tests/functional/com/android/documentsui/RenameDocumentUiTest.java +++ b/tests/functional/com/android/documentsui/RenameDocumentUiTest.java @@ -16,9 +16,8 @@ package com.android.documentsui; -import android.support.test.uiautomator.UiObjectNotFoundException; - import androidx.test.filters.LargeTest; +import androidx.test.uiautomator.UiObjectNotFoundException; import com.android.documentsui.files.FilesActivity; import com.android.documentsui.util.VersionUtils; diff --git a/tests/unit/com/android/documentsui/RecentsLoaderTests.java b/tests/unit/com/android/documentsui/RecentsLoaderTests.java index d95e9243c..915a3bd24 100644 --- a/tests/unit/com/android/documentsui/RecentsLoaderTests.java +++ b/tests/unit/com/android/documentsui/RecentsLoaderTests.java @@ -56,7 +56,6 @@ public class RecentsLoaderTests { private TestEnv mEnv; private TestActivity mActivity; private RecentsLoader mLoader; - private boolean mContentChanged; @Before public void setUp() { @@ -148,12 +147,13 @@ public class RecentsLoaderTests { @Test public void testContentsUpdate_observable() throws Exception { - CountDownLatch latch = new CountDownLatch(1); - Runnable callback = () -> { - latch.countDown(); - mContentChanged = true; - }; - mLoader.setObserver(new LockingContentObserver(new ContentLock(), callback)); + final CountDownLatch latch = new CountDownLatch(1); + + // Please be mindful of the fact that the callback will be invoked on the Main (aka UI) + // thread, while the test itself is running on another (dedicated) thread. + final Runnable onContentChangedCallback = latch::countDown; + mLoader.setObserver(new LockingContentObserver( + new ContentLock(), onContentChangedCallback)); final DocumentInfo doc = mEnv.model.createFile("freddy.jpg"); doc.lastModified = System.currentTimeMillis(); @@ -162,12 +162,12 @@ public class RecentsLoaderTests { mLoader.loadInBackground(); - TestCursor c = (TestCursor) mEnv.mockProviders.get(TestProvidersAccess.HOME.authority) + final TestCursor c = (TestCursor) mEnv.mockProviders.get(TestProvidersAccess.HOME.authority) .queryRecentDocuments(null, null); c.mockOnChange(); - latch.await(1, TimeUnit.SECONDS); - assertTrue(mContentChanged); + final boolean onContentChangedCallbackInvoked = latch.await(1, TimeUnit.SECONDS); + assertTrue(onContentChangedCallbackInvoked); } @Test |