Snap for 4647811 from 371404c404 to pi-release

Change-Id: I0869d0a2c8974911201877cb3abae133a16577fb
This commit is contained in:
android-build-team Robot
2018-03-11 08:22:46 +00:00
69 changed files with 9565 additions and 541 deletions

View File

@@ -738,6 +738,19 @@
android:value="true" />
</activity>
<activity
android:name="Settings$ZenModeBlockedEffectsSettingsActivity"
android:label="@string/zen_mode_what_to_block_title"
android:icon="@drawable/ic_settings_notifications"
android:exported="true"
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.notification.ZenModeBlockedEffectsSetting" />
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
<activity
android:name="Settings$ZenModeBehaviorSettingsActivity"
android:label="@string/zen_mode_behavior_settings_title"

View File

@@ -29,7 +29,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="112dp"
android:layout_height="wrap_content"
android:minHeight="112dp"
android:paddingBottom="8dp"
android:orientation="vertical">

View File

@@ -29,7 +29,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="160dp"
android:layout_height="wrap_content"
android:minHeight="160dp"
android:orientation="vertical">
<RelativeLayout

4056
res/values-as/strings.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -138,12 +138,14 @@
<item msgid="477015974247590543">"1 гадзіна"</item>
<item msgid="5198271470953124739">"Ніколі не ўключаць тайм-аўт"</item>
</string-array>
<!-- no translation found for bluetooth_max_connected_audio_devices:0 (834764606877643762) -->
<!-- no translation found for bluetooth_max_connected_audio_devices:1 (4428462068012149533) -->
<!-- no translation found for bluetooth_max_connected_audio_devices:2 (2620881722754455257) -->
<!-- no translation found for bluetooth_max_connected_audio_devices:3 (402831176731135702) -->
<!-- no translation found for bluetooth_max_connected_audio_devices:4 (4923580285404888038) -->
<!-- no translation found for bluetooth_max_connected_audio_devices:5 (3643103044864989283) -->
<string-array name="bluetooth_max_connected_audio_devices">
<item msgid="834764606877643762">"Выкарыстоўваць стандартныя налады сістэмы: <xliff:g id="DEFAULT_BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES">%1$d</xliff:g>"</item>
<item msgid="4428462068012149533">"1"</item>
<item msgid="2620881722754455257">"2"</item>
<item msgid="402831176731135702">"3"</item>
<item msgid="4923580285404888038">"4"</item>
<item msgid="3643103044864989283">"5"</item>
</string-array>
<string-array name="wifi_signal">
<item msgid="2245412278046491293">"Дрэнная"</item>
<item msgid="2042505933058940139">"Дрэнны"</item>

View File

@@ -334,13 +334,29 @@
<string name="date_time_set_timezone" msgid="5045627174274377814">"Часавы пояс"</string>
<string name="date_time_set_date_title" msgid="6928286765325608604">"Дата"</string>
<string name="date_time_set_date" msgid="7021491668550232105">"Задаць дату"</string>
<!-- no translation found for date_time_select_region (5434001881313168586) -->
<skip />
<!-- no translation found for date_time_select_zone (8883690857762652278) -->
<skip />
<!-- no translation found for date_time_select_fixed_offset_time_zones (6084375085203448645) -->
<skip />
<string name="zone_list_menu_sort_alphabetically" msgid="5683377702671088588">"Сартаваць па алфавіце"</string>
<string name="zone_list_menu_sort_by_timezone" msgid="2720190443744884114">"Сартаваць па часавым поясе"</string>
<string name="zone_change_to_from_dst" msgid="118656001224045590">"Змена на <xliff:g id="TIME_TYPE">%1$s</xliff:g> пачынаецца <xliff:g id="TRANSITION_DATE">%2$s</xliff:g>."</string>
<!-- no translation found for zone_info_exemplar_location_and_offset (1359698475641349336) -->
<skip />
<!-- no translation found for zone_info_offset_and_name (164876167707284017) -->
<skip />
<!-- no translation found for zone_info_footer (4192803402331390389) -->
<skip />
<!-- no translation found for zone_info_footer_no_dst (8652423870143056964) -->
<skip />
<string name="zone_time_type_dst" msgid="8850494578766845276">"Летні час"</string>
<string name="zone_time_type_standard" msgid="3462424485380376522">"Стандартны час"</string>
<string name="zone_menu_by_region" msgid="4603214570803607532">"Часавы пояс згодна рэгіёну"</string>
<string name="zone_menu_by_offset" msgid="1172774718486088771">"Часавыя паясы з фіксаваным зрухам"</string>
<!-- no translation found for zone_menu_by_region (7094872254966039844) -->
<skip />
<!-- no translation found for zone_menu_by_offset (5548491286761692269) -->
<skip />
<string name="date_picker_title" msgid="1338210036394128512">"Дата"</string>
<string name="time_picker_title" msgid="483460752287255019">"Час"</string>
<string name="lock_after_timeout" msgid="4590337686681194648">"Аўтаматычная блакіроўка"</string>
@@ -366,7 +382,11 @@
<string name="security_settings_title" msgid="4918904614964215087">"Бяспека і месца"</string>
<string name="encryption_and_credential_settings_title" msgid="6514904533438791561">"Шыфраванне і ўліковыя даныя"</string>
<string name="encryption_and_credential_settings_summary" product="default" msgid="8721883002237981248">"Тэлефон зашыфраваны"</string>
<!-- no translation found for decryption_settings_summary (5671817824042639849) -->
<skip />
<string name="encryption_and_credential_settings_summary" product="tablet" msgid="7200428573872395685">"Прылада зашыфравана"</string>
<!-- no translation found for decryption_settings_summary (5794135636155570977) -->
<skip />
<string name="lockscreen_settings_title" msgid="3922976395527087455">"Параметры блакіроўкі экрана"</string>
<string name="security_settings_summary" msgid="967393342537986570">"Задаць Маё месцазнаходжанне, разблакаванне экрана, блакаванне SIM-карты, блакаванне сховішча ўліковых дадзеных"</string>
<string name="cdma_security_settings_summary" msgid="6068799952798901542">"Устанавіць маё месцазнаходжанне, разблакаванне экрана, блакаванне сховішча ўліковых дадзеных"</string>
@@ -1470,8 +1490,7 @@
<string name="managed_profile_location_switch_title" msgid="6712332547063039683">"Месца для рабочага профілю"</string>
<string name="location_app_level_permissions" msgid="1825588230817081339">"Дазволы на ўзроўні праграм"</string>
<string name="location_category_recent_location_requests" msgid="1938721350424447421">"Апошнія запыты пра месцазнах."</string>
<!-- no translation found for location_recent_location_requests_see_all (9063541547120162593) -->
<skip />
<string name="location_recent_location_requests_see_all" msgid="9063541547120162593">"Паказаць усе"</string>
<string name="location_no_recent_apps" msgid="2800907699722178041">"У апошні час запытаў ад дадаткаў на вызначэнне месцазнаходжання не паступала"</string>
<string name="location_category_location_services" msgid="7437150886946685979">"Службы вызначэння месцазнаходжання"</string>
<string name="location_high_battery_use" msgid="517199943258508020">"Выс. узровень выкарыст. акум."</string>
@@ -2149,6 +2168,10 @@
<item quantity="many">%1$d праграм</item>
<item quantity="other">%1$d праграмы</item>
</plurals>
<!-- no translation found for battery_auto_restriction_title (4698846356558232573) -->
<skip />
<!-- no translation found for battery_auto_restriction_summary (1816325499514435434) -->
<skip />
<string name="dialog_stop_title" msgid="6395127715596746479">"Спыніць праграму?"</string>
<string name="dialog_stop_message" product="default" msgid="4006631636646776488">"Ваш тэлефон не можа нармальна кіраваць зарадам акумулятара, бо <xliff:g id="APP">%1$s</xliff:g> трымае тэлефон у актыўным рэжыме.\n\nВырашыць гэту праблему можна, прымусова спыніўшы праграму.\n\nКалі гэта не дапамагло, трэба выдаліць праграму, каб павысіць прадукцыйнасць акумулятара."</string>
<string name="dialog_stop_message" product="tablet" msgid="2369957934555162428">"Ваш планшэт не можа нармальна кіраваць зарадам акумулятара, бо <xliff:g id="APP">%1$s</xliff:g> трымае планшэт у актыўным рэжыме.\n\nВырашыць гэту праблему можна, прымусова спыніўшы праграму.\n\nКалі гэта не дапамагло, трэба выдаліць праграму, каб павысіць прадукцыйнасць акумулятара."</string>
@@ -2370,8 +2393,7 @@
<string name="credentials_configure_lock_screen_hint" msgid="8058230497337529036">"Перш чым вы зможаце карыстацца сховішчам уліковых даных, трэба наладзіць надзейную блакіроўку экрана прылады"</string>
<string name="credentials_configure_lock_screen_button" msgid="253239765216055321">"БЛАКІРОЎКА ЭКРАНА"</string>
<string name="usage_access_title" msgid="332333405495457839">"Праграмы з доступам да даных"</string>
<!-- no translation found for emergency_tone_title (254495218194925271) -->
<skip />
<string name="emergency_tone_title" msgid="254495218194925271">"Сігнал набору нумару ў аварыйнай сітуацыі"</string>
<string name="emergency_tone_summary" msgid="722259232924572153">"Задаць паводзіны на выпадак экстранага выкліку"</string>
<string name="privacy_settings_title" msgid="2978878794187459190">"Рэзервовае капіраванне"</string>
<string name="backup_section_title" msgid="7952232291452882740">"Рэзервовае капіяванне і аднаўленне"</string>
@@ -2990,12 +3012,9 @@
<string name="dock_audio_media_title" msgid="1346838179626123900">"Уключыць док-дынамік"</string>
<string name="dock_audio_media_disabled" msgid="3430953622491538080">"Усё аўдыё"</string>
<string name="dock_audio_media_enabled" msgid="667849382924908673">"Толькі медыяаўдыё"</string>
<!-- no translation found for emergency_tone_silent (3750231842974733677) -->
<skip />
<!-- no translation found for emergency_tone_alert (8523447641290736852) -->
<skip />
<!-- no translation found for emergency_tone_vibrate (2278872257053690683) -->
<skip />
<string name="emergency_tone_silent" msgid="3750231842974733677">"Без гуку"</string>
<string name="emergency_tone_alert" msgid="8523447641290736852">"Танальныя сігналы"</string>
<string name="emergency_tone_vibrate" msgid="2278872257053690683">"Вібрацыя"</string>
<string name="boot_sounds_title" msgid="567029107382343709">"Гукі пры ўключэнні"</string>
<string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Ніколі"</string>
<plurals name="zen_mode_settings_summary_on" formatted="false" msgid="7346979080337117366">
@@ -3187,9 +3206,7 @@
<string name="zen_mode_choose_rule_type" msgid="5423746638871953459">"Выберыце тып правіла"</string>
<string name="zen_mode_delete_rule_confirmation" msgid="6237882294348570283">"Выдаліць правіла “<xliff:g id="RULE">%1$s</xliff:g>”?"</string>
<string name="zen_mode_delete_rule_button" msgid="4248741120307752294">"Выдаліць"</string>
<string name="zen_mode_rule_type" msgid="2289413469580142888">"Тып правіла"</string>
<string name="zen_mode_rule_type_unknown" msgid="3049377282766700600">"Невядома"</string>
<string name="zen_mode_configure_rule" msgid="8865785428056490305">"Наладзіць правіла"</string>
<string name="zen_mode_app_set_behavior" msgid="1534429320064381355">"Гэтыя налады немагчыма змяніць зараз. Праграма (<xliff:g id="APP_NAME">%1$s</xliff:g>) аўтаматычна ўключыла рэжым \"Не турбаваць\" з карыстальніцкімі паводзінамі."</string>
<string name="zen_mode_unknown_app_set_behavior" msgid="2558968232814237874">"Гэтыя налады немагчыма змяніць зараз. Праграма аўтаматычна ўключыла рэжым \"Не турбаваць\" з карыстальніцкімі паводзінамі."</string>
<string name="zen_mode_qs_set_behavior" msgid="6200424436456086312">"Гэтыя налады немагчыма змяніць зараз. Рэжым \"Не турбаваць\" быў уключаны ўручную з карыстальніцкімі паводзінамі."</string>
@@ -3226,8 +3243,10 @@
<string name="zen_mode_from_starred" msgid="2678345811950997027">"Толькі ад кантактаў, пазначаных зоркай"</string>
<string name="zen_mode_from_none" msgid="8219706639954614136">"Ні ад каго"</string>
<string name="zen_mode_alarms" msgid="2165302777886552926">"Будзільнікі"</string>
<string name="zen_mode_media_system_other" msgid="5937422836400161702">"Медыя"</string>
<string name="zen_mode_media_system_other_secondary_text" msgid="785130341801887185">"Уключае такую рэакцыю сістэмы як гукі націску і зарадкі"</string>
<!-- no translation found for zen_mode_media (8808264142134422380) -->
<skip />
<!-- no translation found for zen_mode_system (1735424656149706110) -->
<skip />
<string name="zen_mode_reminders" msgid="5458502056440485730">"Напаміны"</string>
<string name="zen_mode_events" msgid="7914446030988618264">"Падзеі"</string>
<string name="zen_mode_all_callers" msgid="584186167367236922">"Усе абаненты"</string>
@@ -3459,10 +3478,8 @@
<string name="usb_use_MIDI_desc" msgid="8473936990076693175">"Выкарыстоўваць гэту прыладу ў якасці MIDI"</string>
<string name="usb_use" msgid="3372728031108932425">"Выкарыстоўваць USB для"</string>
<string name="usb_use_also" msgid="557340935190819370">"Іншыя рэжымы працы USB"</string>
<!-- no translation found for usb_default_label (4217189967858707974) -->
<skip />
<!-- no translation found for usb_default_info (8864535445796200695) -->
<skip />
<string name="usb_default_label" msgid="4217189967858707974">"Стандартная канфігурацыя USB"</string>
<string name="usb_default_info" msgid="8864535445796200695">"Гэтыя налады прымяняюцца, калі падключана іншая прылада, а ваш тэлефон разблакіраваны. Падключайце толькі давераныя прылады."</string>
<string name="usb_pref" msgid="1400617804525116158">"USB"</string>
<string name="usb_summary_charging_only" msgid="7544327009143659751">"Зарадка гэтай прылады"</string>
<string name="usb_summary_power_only" msgid="1996391096369798526">"Зарадка падключанай прылады"</string>
@@ -3991,14 +4008,21 @@
<string name="bluetooth_on_while_driving_pref" msgid="2460847604498343330">"За рулём выкарыстоўвайце Bluetooth"</string>
<string name="bluetooth_on_while_driving_summary" msgid="3196190732516898541">"Аўтаматычна ўключаць Bluetooth, калі вы за рулём"</string>
<string name="dev_android_o_battery_settings_title" msgid="2926578228655006762">"Налады акумулятара для Android 8.0"</string>
<!-- no translation found for change_wifi_state_title (2640523995824431999) -->
<string name="change_wifi_state_title" msgid="2640523995824431999">"Уключэнне і выключэнне Wi-Fi"</string>
<string name="keywords_change_wifi_state" msgid="1439807171750715923">"уключэнне і выключэнне Wi-Fi"</string>
<string name="change_wifi_state_app_detail_title" msgid="1022360625069880993">"Уключэнне і выключэнне Wi-Fi"</string>
<string name="change_wifi_state_app_detail_switch" msgid="724818064600933957">"Дазволіць уключэнне і выключэнне Wi-Fi"</string>
<string name="change_wifi_state_app_detail_summary" msgid="2511212187129042304">"Дазволіць гэтай праграме рабіць падключэнні па Wi-Fi, а таксама ўключаць і выключаць гэту функцыю."</string>
<!-- no translation found for media_output_title (115223550977351699) -->
<skip />
<!-- no translation found for keywords_change_wifi_state (1439807171750715923) -->
<!-- no translation found for media_output_summary (6839458453831567167) -->
<skip />
<!-- no translation found for change_wifi_state_app_detail_title (1022360625069880993) -->
<!-- no translation found for media_output_summary (7217221078578554515) -->
<skip />
<!-- no translation found for change_wifi_state_app_detail_switch (724818064600933957) -->
<!-- no translation found for media_output_summary (5677420090811068649) -->
<skip />
<!-- no translation found for change_wifi_state_app_detail_summary (2511212187129042304) -->
<!-- no translation found for media_out_summary_ongoing_call_state (3533731701018680693) -->
<skip />
<!-- no translation found for media_output_summary_unavailable (7970304720507697019) -->
<skip />
</resources>

4058
res/values-or/strings.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -330,13 +330,20 @@
<string name="date_time_set_timezone" msgid="5045627174274377814">"Selecionar fuso horário"</string>
<string name="date_time_set_date_title" msgid="6928286765325608604">"Data"</string>
<string name="date_time_set_date" msgid="7021491668550232105">"Definir data"</string>
<string name="date_time_select_region" msgid="5434001881313168586">"Região"</string>
<string name="date_time_select_zone" msgid="8883690857762652278">"Fuso horário"</string>
<string name="date_time_select_fixed_offset_time_zones" msgid="6084375085203448645">"Selecionar compensação de UTC"</string>
<string name="zone_list_menu_sort_alphabetically" msgid="5683377702671088588">"Classificar em ordem alfabética"</string>
<string name="zone_list_menu_sort_by_timezone" msgid="2720190443744884114">"Classificar por fuso horário"</string>
<string name="zone_change_to_from_dst" msgid="118656001224045590">"O <xliff:g id="TIME_TYPE">%1$s</xliff:g> começa em: <xliff:g id="TRANSITION_DATE">%2$s</xliff:g>."</string>
<string name="zone_info_exemplar_location_and_offset" msgid="1359698475641349336">"<xliff:g id="EXEMPLAR_LOCATION">%1$s</xliff:g> (<xliff:g id="OFFSET">%2$s</xliff:g>)"</string>
<string name="zone_info_offset_and_name" msgid="164876167707284017">"<xliff:g id="TIME_TYPE">%2$s</xliff:g> (<xliff:g id="OFFSET">%1$s</xliff:g>)"</string>
<string name="zone_info_footer" msgid="4192803402331390389">"Usa <xliff:g id="OFFSET_AND_NAME">%1$s</xliff:g>. <xliff:g id="DST_TIME_TYPE">%2$s</xliff:g> começa em <xliff:g id="TRANSITION_DATE">%3$s</xliff:g>."</string>
<string name="zone_info_footer_no_dst" msgid="8652423870143056964">"Usa <xliff:g id="OFFSET_AND_NAME">%1$s</xliff:g>. Sem horário de verão."</string>
<string name="zone_time_type_dst" msgid="8850494578766845276">"Horário de verão"</string>
<string name="zone_time_type_standard" msgid="3462424485380376522">"Horário padrão"</string>
<string name="zone_menu_by_region" msgid="4603214570803607532">"Fuso horário por região"</string>
<string name="zone_menu_by_offset" msgid="1172774718486088771">"Fusos horários com diferença fixa"</string>
<string name="zone_menu_by_region" msgid="7094872254966039844">"Mostrar fusos horários por região"</string>
<string name="zone_menu_by_offset" msgid="5548491286761692269">"Mostrar fusos horários por compensação de UTC"</string>
<string name="date_picker_title" msgid="1338210036394128512">"Data"</string>
<string name="time_picker_title" msgid="483460752287255019">"Hora"</string>
<string name="lock_after_timeout" msgid="4590337686681194648">"Bloquear automaticamente"</string>
@@ -362,7 +369,11 @@
<string name="security_settings_title" msgid="4918904614964215087">"Segurança e local"</string>
<string name="encryption_and_credential_settings_title" msgid="6514904533438791561">"Criptografia e credenciais"</string>
<string name="encryption_and_credential_settings_summary" product="default" msgid="8721883002237981248">"Smartphone criptografado"</string>
<!-- no translation found for decryption_settings_summary (5671817824042639849) -->
<skip />
<string name="encryption_and_credential_settings_summary" product="tablet" msgid="7200428573872395685">"Dispositivo criptografado"</string>
<!-- no translation found for decryption_settings_summary (5794135636155570977) -->
<skip />
<string name="lockscreen_settings_title" msgid="3922976395527087455">"Preferências da tela de bloqueio"</string>
<string name="security_settings_summary" msgid="967393342537986570">"Definir Meu local, desbloqueio de tela, bloqueio do SIM e do armazenamento de credenciais"</string>
<string name="cdma_security_settings_summary" msgid="6068799952798901542">"Definir o Meu local, o desbloqueio de tela, o bloqueio do armazenamento de credenciais"</string>
@@ -2095,6 +2106,10 @@
<item quantity="one">%1$d app</item>
<item quantity="other">%1$d apps</item>
</plurals>
<!-- no translation found for battery_auto_restriction_title (4698846356558232573) -->
<skip />
<!-- no translation found for battery_auto_restriction_summary (1816325499514435434) -->
<skip />
<string name="dialog_stop_title" msgid="6395127715596746479">"Parar o app?"</string>
<string name="dialog_stop_message" product="default" msgid="4006631636646776488">"Não é possível gerenciar a bateria do smartphone normalmente, porque o app <xliff:g id="APP">%1$s</xliff:g> o mantém ativado.\n\nPara tentar resolver esse problema, você pode forçar a parada do app.\n\nSe isso continuar acontecendo, talvez seja necessário desinstalá-lo para melhorar o desempenho da bateria."</string>
<string name="dialog_stop_message" product="tablet" msgid="2369957934555162428">"Não é possível gerenciar a bateria do tablet normalmente, porque o app <xliff:g id="APP">%1$s</xliff:g> o mantém ativado.\n\nPara tentar resolver esse problema, você pode forçar a parada do app.\n\nSe isso continuar acontecendo, talvez seja necessário desinstalá-lo para melhorar o desempenho da bateria."</string>
@@ -3144,8 +3159,10 @@
<string name="zen_mode_from_starred" msgid="2678345811950997027">"Apenas de contatos marcados com estrela"</string>
<string name="zen_mode_from_none" msgid="8219706639954614136">"Nenhuma"</string>
<string name="zen_mode_alarms" msgid="2165302777886552926">"Alarmes"</string>
<string name="zen_mode_media_system_other" msgid="5937422836400161702">"Mídia"</string>
<string name="zen_mode_media_system_other_secondary_text" msgid="785130341801887185">"Inclui feedback do sistema, como sons de toque e carregamento"</string>
<!-- no translation found for zen_mode_media (8808264142134422380) -->
<skip />
<!-- no translation found for zen_mode_system (1735424656149706110) -->
<skip />
<string name="zen_mode_reminders" msgid="5458502056440485730">"Lembretes"</string>
<string name="zen_mode_events" msgid="7914446030988618264">"Eventos"</string>
<string name="zen_mode_all_callers" msgid="584186167367236922">"Todos os autores de chamadas"</string>
@@ -3861,4 +3878,16 @@
<string name="change_wifi_state_app_detail_title" msgid="1022360625069880993">"Ativar e desativar o Wi-Fi"</string>
<string name="change_wifi_state_app_detail_switch" msgid="724818064600933957">"Permitir alternância do Wi-Fi"</string>
<string name="change_wifi_state_app_detail_summary" msgid="2511212187129042304">"Permitir que esse app altere o estado do Wi-Fi, inclusive se conectando ao Wi-Fi e ativando-o ou desativando-o."</string>
<!-- no translation found for media_output_title (115223550977351699) -->
<skip />
<!-- no translation found for media_output_summary (6839458453831567167) -->
<skip />
<!-- no translation found for media_output_summary (7217221078578554515) -->
<skip />
<!-- no translation found for media_output_summary (5677420090811068649) -->
<skip />
<!-- no translation found for media_out_summary_ongoing_call_state (3533731701018680693) -->
<skip />
<!-- no translation found for media_output_summary_unavailable (7970304720507697019) -->
<skip />
</resources>

View File

@@ -6918,8 +6918,8 @@
<!-- Do not disturb: Title for the Do not Disturb dialog to turn on Do not disturb. [CHAR LIMIT=50]-->
<string name="zen_mode_settings_turn_on_dialog_title">Turn on Do Not Disturb</string>
<!-- Do not disturb: Title for the behaviors option and associated settings page. [CHAR LIMIT=30] -->
<string name="zen_mode_behavior_settings_title">Behavior</string>
<!-- Do not disturb: Title for the page describing what can bypass DND. [CHAR LIMIT=30] -->
<string name="zen_mode_behavior_settings_title">Exceptions</string>
<!-- Do not disturb: Instructions indicating what types of sounds can bypass DND. [CHAR LIMIT=52] -->
<string name="zen_mode_behavior_allow_title">Allow sounds and vibrations from</string>
@@ -6972,6 +6972,34 @@
<!-- Do not disturb: Subtitle for the Visual signals option to toggle on/off visual signals/alerts when the screen is on/when screen is off. [CHAR LIMIT=30] -->
<string name="zen_mode_visual_signals_settings_subtitle">Allow visual signals</string>
<!-- Do not disturb: what to block title [CHAR LIMIT = 60] -->
<string name="zen_mode_what_to_block_title">What to block</string>
<!-- Do not disturb: what to block > effects title [CHAR LIMIT = 60] -->
<string name="zen_mode_block_effects_title">When notifications arrive</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_sound">Mute sound and vibration</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_intent">Don\'t turn on screen</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_light">Don\'t blink light</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_peek">Don\'t pop notifications on screen</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_status">Hide status bar icons</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_badge">Hide notification dots</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_ambient">Hide from ambient display</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_list">Hide from notification list</string>
<!-- Do not disturb: what to block summary, only sound and vibration -->
<string name="zen_mode_block_effect_summary_sound">Sound and vibration</string>
<!-- Do not disturb: what to block summary, sound vibration and some visual signals-->
<string name="zen_mode_block_effect_summary_some">Sound, vibration, and some visual signs of notifications</string>
<!-- Do not disturb: what to block summary, all effects -->
<string name="zen_mode_block_effect_summary_all">Sound, vibration, and visual signs of notifications</string>
<!-- Do not disturb: Button to add new automatic rule to DND. [CHAR LIMIT=30] -->
<string name="zen_mode_add">Add</string>

View File

@@ -19,71 +19,51 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="zen_mode_behavior_settings_page"
android:title="@string/zen_mode_behavior_settings_title"
settings:initialExpandedChildrenCount="8">
android:title="@string/zen_mode_behavior_settings_title" >
<PreferenceCategory
android:title="@string/zen_mode_behavior_allow_title"
android:key="zen_mode_behavior_allow_preferences">
<!-- Alarms -->
<SwitchPreference
android:key="zen_mode_alarms"
android:title="@string/zen_mode_alarms"/>
<!-- Alarms -->
<SwitchPreference
android:key="zen_mode_alarms"
android:title="@string/zen_mode_alarms"/>
<!-- Media -->
<SwitchPreference
android:key="zen_mode_media"
android:title="@string/zen_mode_media"/>
<!-- Media -->
<SwitchPreference
android:key="zen_mode_media"
android:title="@string/zen_mode_media"/>
<!-- System -->
<SwitchPreference
android:key="zen_mode_system"
android:title="@string/zen_mode_system"/>
<!-- System -->
<SwitchPreference
android:key="zen_mode_system"
android:title="@string/zen_mode_system"/>
<!-- Reminders -->
<SwitchPreference
android:key="zen_mode_reminders"
android:title="@string/zen_mode_reminders"/>
<!-- Reminders -->
<SwitchPreference
android:key="zen_mode_reminders"
android:title="@string/zen_mode_reminders"/>
<!-- Events -->
<SwitchPreference
android:key="zen_mode_events"
android:title="@string/zen_mode_events"/>
<!-- Events -->
<SwitchPreference
android:key="zen_mode_events"
android:title="@string/zen_mode_events"/>
<!-- Messages -->
<ListPreference
android:key="zen_mode_messages"
android:title="@string/zen_mode_messages"
android:entries="@array/zen_mode_contacts_entries"
android:entryValues="@array/zen_mode_contacts_values"/>
<!-- Messages -->
<ListPreference
android:key="zen_mode_messages"
android:title="@string/zen_mode_messages"
android:entries="@array/zen_mode_contacts_entries"
android:entryValues="@array/zen_mode_contacts_values"/>
<!-- Calls -->
<ListPreference
android:key="zen_mode_calls"
android:title="@string/zen_mode_calls"
android:entries="@array/zen_mode_contacts_entries"
android:entryValues="@array/zen_mode_contacts_values"/>
<!-- Calls -->
<ListPreference
android:key="zen_mode_calls"
android:title="@string/zen_mode_calls"
android:entries="@array/zen_mode_contacts_entries"
android:entryValues="@array/zen_mode_contacts_values"/>
<!-- Repeat callers -->
<SwitchPreference
android:key="zen_mode_repeat_callers"
android:title="@string/zen_mode_repeat_callers" />
</PreferenceCategory>
<PreferenceCategory
android:title="@string/zen_mode_visual_signals_settings_subtitle"
android:key="zen_mode_visual_signals_preferences">
<SwitchPreference android:key="zen_mode_screen_on"
android:title="@string/zen_mode_screen_on"
android:summary="@string/zen_mode_screen_on_summary" />
<SwitchPreference android:key="zen_mode_screen_off"
android:title="@string/zen_mode_screen_off"
android:summary="@string/zen_mode_screen_off_summary" />
</PreferenceCategory>
<!-- Repeat callers -->
<SwitchPreference
android:key="zen_mode_repeat_callers"
android:title="@string/zen_mode_repeat_callers" />
<com.android.settingslib.widget.FooterPreference />

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:key="zen_mode_block_settings_page">
<!-- sound vibration -->
<CheckBoxPreference
android:key="zen_effect_sound"
android:title="@string/zen_mode_block_effect_sound"
android:enabled="false" />
<PreferenceCategory
android:title="@string/zen_mode_block_effects_title"
android:key="zen_mode_block_vis_effects">
<CheckBoxPreference
android:key="zen_effect_intent"
android:title="@string/zen_mode_block_effect_intent" />
<CheckBoxPreference
android:key="zen_effect_light"
android:title="@string/zen_mode_block_effect_light" />
<CheckBoxPreference
android:key="zen_effect_peek"
android:title="@string/zen_mode_block_effect_peek" />
<CheckBoxPreference
android:key="zen_effect_status"
android:title="@string/zen_mode_block_effect_status" />
<CheckBoxPreference
android:key="zen_effect_badge"
android:title="@string/zen_mode_block_effect_badge" />
<CheckBoxPreference
android:key="zen_effect_ambient"
android:title="@string/zen_mode_block_effect_ambient" />
<CheckBoxPreference
android:key="zen_effect_list"
android:title="@string/zen_mode_block_effect_list" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -19,7 +19,13 @@
android:key="zen_mode_settings"
android:title="@string/zen_mode_settings_title">
<!-- Priority behavior settings -->
<!-- What to block (effects) -->
<Preference
android:key="zen_mode_block_effects_settings"
android:title="@string/zen_mode_what_to_block_title"
android:fragment="com.android.settings.notification.ZenModeBlockedEffectsSettings" />
<!-- Behavior settings (exceptions) -->
<Preference
android:key="zen_mode_behavior_settings"
android:title="@string/zen_mode_behavior_settings_title"

View File

@@ -100,6 +100,7 @@ public class Settings extends SettingsActivity {
public static class PrintJobSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeBehaviorSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeBlockedEffectsSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeAutomationSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeScheduleRuleSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeEventRuleSettingsActivity extends SettingsActivity { /* empty */ }

View File

@@ -16,12 +16,14 @@
package com.android.settings.bluetooth;
import android.content.pm.PackageManager;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -30,7 +32,7 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Controller that shows received files
*/
public class BluetoothFilesPreferenceController extends AbstractPreferenceController
public class BluetoothFilesPreferenceController extends BasePreferenceController
implements PreferenceControllerMixin {
private static final String TAG = "BluetoothFilesPrefCtrl";
@@ -47,13 +49,15 @@ public class BluetoothFilesPreferenceController extends AbstractPreferenceContro
private MetricsFeatureProvider mMetricsFeatureProvider;
public BluetoothFilesPreferenceController(Context context) {
super(context);
super(context, KEY_RECEIVED_FILES);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
@Override
public boolean isAvailable() {
return true;
public int getAvailabilityStatus() {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
? AVAILABLE
: DISABLED_UNSUPPORTED;
}
@Override

View File

@@ -23,6 +23,7 @@ import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
@@ -71,7 +72,10 @@ public class BluetoothPairingDetail extends DeviceListPreferenceFragment impleme
@Override
public void onStart() {
super.onStart();
if (mLocalManager == null){
Log.e(TAG, "Bluetooth is not supported on this device");
return;
}
updateBluetooth();
mAvailableDevicesCategory.setProgress(mLocalAdapter.isDiscovering());
}
@@ -89,7 +93,10 @@ public class BluetoothPairingDetail extends DeviceListPreferenceFragment impleme
@Override
public void onStop() {
super.onStop();
if (mLocalManager == null){
Log.e(TAG, "Bluetooth is not supported on this device");
return;
}
// Make the device only visible to connected devices.
mAlwaysDiscoverable.stop();
disableScanning();

View File

@@ -15,15 +15,18 @@
*/
package com.android.settings.connecteddevice;
import android.content.pm.PackageManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.connecteddevice.usb.ConnectedUsbDeviceUpdater;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.bluetooth.ConnectedBluetoothDeviceUpdater;
import com.android.settings.search.ResultPayload;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -35,7 +38,7 @@ import com.android.settingslib.core.lifecycle.events.OnStop;
* Controller to maintain the {@link android.support.v7.preference.PreferenceGroup} for all
* connected devices. It uses {@link DevicePreferenceCallback} to add/remove {@link Preference}
*/
public class ConnectedDeviceGroupController extends AbstractPreferenceController
public class ConnectedDeviceGroupController extends BasePreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop,
DevicePreferenceCallback {
@@ -47,7 +50,7 @@ public class ConnectedDeviceGroupController extends AbstractPreferenceController
private ConnectedUsbDeviceUpdater mConnectedUsbDeviceUpdater;
public ConnectedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle) {
super(fragment.getContext());
super(fragment.getContext(), KEY);
init(lifecycle, new ConnectedBluetoothDeviceUpdater(fragment, this),
new ConnectedUsbDeviceUpdater(fragment, this));
}
@@ -56,7 +59,7 @@ public class ConnectedDeviceGroupController extends AbstractPreferenceController
ConnectedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle,
BluetoothDeviceUpdater bluetoothDeviceUpdater,
ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater) {
super(fragment.getContext());
super(fragment.getContext(), KEY);
init(lifecycle, bluetoothDeviceUpdater, connectedUsbDeviceUpdater);
}
@@ -75,17 +78,21 @@ public class ConnectedDeviceGroupController extends AbstractPreferenceController
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
mPreferenceGroup.setVisible(false);
if (isAvailable()) {
mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
mPreferenceGroup.setVisible(false);
mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
mBluetoothDeviceUpdater.forceUpdate();
mConnectedUsbDeviceUpdater.initUsbPreference(screen.getContext());
mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
mBluetoothDeviceUpdater.forceUpdate();
mConnectedUsbDeviceUpdater.initUsbPreference(screen.getContext());
}
}
@Override
public boolean isAvailable() {
return true;
public int getAvailabilityStatus() {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
? AVAILABLE
: DISABLED_UNSUPPORTED;
}
@Override
@@ -111,7 +118,7 @@ public class ConnectedDeviceGroupController extends AbstractPreferenceController
private void init(Lifecycle lifecycle, BluetoothDeviceUpdater bluetoothDeviceUpdater,
ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater) {
if (lifecycle != null) {
if (lifecycle != null && isAvailable()) {
lifecycle.addObserver(this);
}
mBluetoothDeviceUpdater = bluetoothDeviceUpdater;

View File

@@ -15,6 +15,7 @@
*/
package com.android.settings.connecteddevice;
import android.content.pm.PackageManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
@@ -22,6 +23,7 @@ import android.support.v7.preference.PreferenceScreen;
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.bluetooth.SavedBluetoothDeviceUpdater;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -34,7 +36,7 @@ import com.android.settingslib.core.lifecycle.events.OnStop;
* Controller to maintain the {@link PreferenceGroup} for all
* saved devices. It uses {@link DevicePreferenceCallback} to add/remove {@link Preference}
*/
public class SavedDeviceGroupController extends AbstractPreferenceController
public class SavedDeviceGroupController extends BasePreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop,
DevicePreferenceCallback {
@@ -45,14 +47,14 @@ public class SavedDeviceGroupController extends AbstractPreferenceController
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
public SavedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle) {
super(fragment.getContext());
super(fragment.getContext(), KEY);
init(lifecycle, new SavedBluetoothDeviceUpdater(fragment, SavedDeviceGroupController.this));
}
@VisibleForTesting
SavedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle,
BluetoothDeviceUpdater bluetoothDeviceUpdater) {
super(fragment.getContext());
super(fragment.getContext(), KEY);
init(lifecycle, bluetoothDeviceUpdater);
}
@@ -68,15 +70,19 @@ public class SavedDeviceGroupController extends AbstractPreferenceController
@Override
public void displayPreference(PreferenceScreen screen) {
mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
mPreferenceGroup.setVisible(false);
mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
mBluetoothDeviceUpdater.forceUpdate();
if (isAvailable()) {
mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
mPreferenceGroup.setVisible(false);
mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
mBluetoothDeviceUpdater.forceUpdate();
}
}
@Override
public boolean isAvailable() {
return true;
public int getAvailabilityStatus() {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
? AVAILABLE
: DISABLED_UNSUPPORTED;
}
@Override
@@ -101,7 +107,7 @@ public class SavedDeviceGroupController extends AbstractPreferenceController
}
private void init(Lifecycle lifecycle, BluetoothDeviceUpdater bluetoothDeviceUpdater) {
if (lifecycle != null) {
if (lifecycle != null && isAvailable()) {
lifecycle.addObserver(this);
}
mBluetoothDeviceUpdater = bluetoothDeviceUpdater;

View File

@@ -119,7 +119,7 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
}
final Icon icon = suggestion.getIcon();
final Drawable drawable = mCache.getIcon(icon);
if (drawable != null) {
if (drawable != null && (suggestion.getFlags() & Suggestion.FLAG_ICON_TINTABLE) != 0) {
drawable.setTint(Utils.getColorAccent(mContext));
}
holder.icon.setImageDrawable(drawable);

View File

@@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
/**
* Render a list of {@class TimeZoneInfo} into the list view in {@class BaseTimeZonePicker}
@@ -135,8 +136,11 @@ public abstract class BaseTimeZoneInfoPicker extends BaseTimeZonePicker {
name = mTimeZoneInfo.getStandardName();
}
}
if (name == null) {
return mTimeZoneInfo.getGmtOffset();
// Ignore name / GMT offset if the title shows the same information
if (name == null || name.equals(mTitle)) {
CharSequence gmtOffset = mTimeZoneInfo.getGmtOffset();
return gmtOffset == null || gmtOffset.toString().equals(mTitle) ? "" : gmtOffset;
} else {
return SpannableUtil.getResourcesText(mResources,
R.string.zone_info_offset_and_name, mTimeZoneInfo.getGmtOffset(), name);

View File

@@ -146,12 +146,6 @@ public abstract class BaseTimeZonePicker extends InstrumentedFragment
return false;
}
@Override
public int getMetricsCategory() {
// TODO: use a new metrics id?
return MetricsEvent.ZONE_PICKER;
}
public interface OnListItemClickListener {
void onListItemClick(int position);
}

View File

@@ -18,6 +18,7 @@ package com.android.settings.datetime.timezone;
import android.icu.util.TimeZone;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.datetime.timezone.model.TimeZoneData;
@@ -42,6 +43,11 @@ public class FixedOffsetPicker extends BaseTimeZoneInfoPicker {
R.string.search_settings, false, false);
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.SETTINGS_ZONE_PICKER_FIXED_OFFSET;
}
@Override
public List<TimeZoneInfo> getAllTimeZoneInfos(TimeZoneData timeZoneData) {
return loadFixedOffsets();

View File

@@ -17,7 +17,8 @@
package com.android.settings.datetime.timezone;
import android.content.Context;
import android.support.v7.preference.Preference;
import com.android.settings.R;
public class FixedOffsetPreferenceController extends BaseTimeZonePreferenceController {
@@ -31,8 +32,18 @@ public class FixedOffsetPreferenceController extends BaseTimeZonePreferenceContr
@Override
public CharSequence getSummary() {
// This is a Spannable object, which contains TTS span. It shouldn't be converted to String.
return mTimeZoneInfo == null ? "" : mTimeZoneInfo.getGmtOffset();
if (mTimeZoneInfo == null) {
return "";
}
String standardName = mTimeZoneInfo.getStandardName();
if (standardName == null) {
return mTimeZoneInfo.getGmtOffset();
} else {
// GmtOffset is Spannable, which contains TTS span. It shouldn't be converted to String.
return SpannableUtil.getResourcesText(mContext.getResources(),
R.string.zone_info_offset_and_name, mTimeZoneInfo.getGmtOffset(), standardName);
}
}
public void setTimeZoneInfo(TimeZoneInfo timeZoneInfo) {

View File

@@ -24,6 +24,7 @@ import android.icu.text.LocaleDisplayNames;
import android.os.Bundle;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.datetime.timezone.model.FilteredCountryTimeZones;
@@ -49,6 +50,11 @@ public class RegionSearchPicker extends BaseTimeZonePicker {
super(R.string.date_time_select_region, R.string.search_settings, true, true);
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.SETTINGS_ZONE_PICKER_REGION;
}
@Override
protected BaseTimeZoneAdapter createAdapter(TimeZoneData timeZoneData) {
mTimeZoneData = timeZoneData;
@@ -104,56 +110,25 @@ public class RegionSearchPicker extends BaseTimeZonePicker {
private List<RegionItem> createAdapterItem(Set<String> regionIds) {
final Collator collator = Collator.getInstance(getLocale());
final TreeSet<RegionItem> items = new TreeSet<>(new RegionInfoComparator(collator));
final Paint paint = new Paint();
final LocaleDisplayNames localeDisplayNames = LocaleDisplayNames.getInstance(getLocale());
long i = 0;
for (String regionId : regionIds) {
String name = localeDisplayNames.regionDisplayName(regionId);
String regionalIndicator = createRegionalIndicator(regionId, paint);
items.add(new RegionItem(i++, regionId, name, regionalIndicator));
items.add(new RegionItem(i++, regionId, name));
}
return new ArrayList<>(items);
}
/**
* Create a Unicode Region Indicator Symbol for a given region id (a.k.a flag emoji). If the
* system can't render a flag for this region or the input is not a region id, this returns
* {@code null}.
*
* @param id the two-character region id.
* @param paint Paint contains the glyph
* @return a String representing the flag of the region or {@code null}.
*/
private static String createRegionalIndicator(String id, Paint paint) {
if (id.length() != 2) {
return null;
}
final char c1 = id.charAt(0);
final char c2 = id.charAt(1);
if ('A' > c1 || c1 > 'Z' || 'A' > c2 || c2 > 'Z') {
return null;
}
// Regional Indicator A is U+1F1E6 which is 0xD83C 0xDDE6 in UTF-16.
final String regionalIndicator = new String(
new char[]{0xd83c, (char) (0xdde6 - 'A' + c1), 0xd83c, (char) (0xdde6 - 'A' + c2)});
if (!paint.hasGlyph(regionalIndicator)) {
return null;
}
return regionalIndicator;
}
private static class RegionItem implements BaseTimeZoneAdapter.AdapterItem {
private final String mId;
private final String mName;
private final String mRegionalIndicator;
private final long mItemId;
private final String[] mSearchKeys;
RegionItem(long itemId, String id, String name, String regionalIndicator) {
RegionItem(long itemId, String id, String name) {
mId = id;
mName = name;
mRegionalIndicator = regionalIndicator;
mItemId = itemId;
// Allow to search with ISO_3166-1 alpha-2 code. It's handy for english users in some
// countries, e.g. US for United States. It's not best search keys for users, but
@@ -177,7 +152,7 @@ public class RegionSearchPicker extends BaseTimeZonePicker {
@Override
public String getIconText() {
return mRegionalIndicator;
return null;
}
@Override

View File

@@ -22,6 +22,7 @@ import android.icu.util.TimeZone;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.datetime.timezone.model.FilteredCountryTimeZones;
import com.android.settings.datetime.timezone.model.TimeZoneData;
@@ -46,6 +47,11 @@ public class RegionZonePicker extends BaseTimeZoneInfoPicker {
super(R.string.date_time_select_zone, R.string.search_settings, true, false);
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.SETTINGS_ZONE_PICKER_TIME_ZONE;
}
/**
* Add the extra region id into the result.
*/

View File

@@ -98,7 +98,7 @@ public class TimeZoneSettings extends DashboardFragment {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
RegionPreferenceController regionPreferenceController =
new RegionPreferenceController(context);
regionPreferenceController.setOnClickListener(this::onRegionPreferenceClicked);
regionPreferenceController.setOnClickListener(this::startRegionPicker);
RegionZonePreferenceController regionZonePreferenceController =
new RegionZonePreferenceController(context);
regionZonePreferenceController.setOnClickListener(this::onRegionZonePreferenceClicked);
@@ -106,7 +106,7 @@ public class TimeZoneSettings extends DashboardFragment {
new TimeZoneInfoPreferenceController(context);
FixedOffsetPreferenceController fixedOffsetPreferenceController =
new FixedOffsetPreferenceController(context);
fixedOffsetPreferenceController.setOnClickListener(this::onFixedOffsetPreferenceClicked);
fixedOffsetPreferenceController.setOnClickListener(this::startFixedOffsetPicker);
controllers.add(regionPreferenceController);
controllers.add(regionZonePreferenceController);
@@ -172,7 +172,7 @@ public class TimeZoneSettings extends DashboardFragment {
}
private void onRegionPreferenceClicked() {
private void startRegionPicker() {
startPickerFragment(RegionSearchPicker.class, new Bundle(), REQUEST_CODE_REGION_PICKER);
}
@@ -183,7 +183,7 @@ public class TimeZoneSettings extends DashboardFragment {
startPickerFragment(RegionZonePicker.class, args, REQUEST_CODE_ZONE_PICKER);
}
private void onFixedOffsetPreferenceClicked() {
private void startFixedOffsetPicker() {
startPickerFragment(FixedOffsetPicker.class, new Bundle(),
REQUEST_CODE_FIXED_OFFSET_ZONE_PICKER);
}
@@ -240,12 +240,18 @@ public class TimeZoneSettings extends DashboardFragment {
setDisplayedRegion(regionId);
setDisplayedTimeZoneInfo(regionId, mSelectedTimeZoneId);
saveTimeZone(regionId, mSelectedTimeZoneId);
// Switch to the region mode if the user switching from the fixed offset
setSelectByRegion(true);
}
private void onFixedOffsetZoneChanged(String tzId) {
mSelectedTimeZoneId = tzId;
setDisplayedFixedOffsetTimeZoneInfo(tzId);
saveTimeZone(null, mSelectedTimeZoneId);
// Switch to the fixed offset mode if the user switching from the region mode
setSelectByRegion(false);
}
private void saveTimeZone(String regionId, String tzId) {
@@ -277,11 +283,11 @@ public class TimeZoneSettings extends DashboardFragment {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_BY_REGION:
setSelectByRegion(true);
startRegionPicker();
return true;
case MENU_BY_OFFSET:
setSelectByRegion(false);
startFixedOffsetPicker();
return true;
default:

View File

@@ -25,6 +25,7 @@ import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
import com.android.settings.R;
import com.android.settings.Utils;
@@ -40,6 +41,7 @@ import com.android.settingslib.core.lifecycle.events.OnStop;
*/
public class AutoBatterySeekBarPreferenceController extends BasePreferenceController implements
LifecycleObserver, OnStart, OnStop, SeekBarPreference.OnPreferenceChangeListener {
private static final String TAG = "AutoBatterySeekBarPreferenceController";
@VisibleForTesting
static final String KEY_AUTO_BATTERY_SEEK_BAR = "battery_saver_seek_bar";
private final int mDefWarnLevel;
@@ -61,6 +63,7 @@ public class AutoBatterySeekBarPreferenceController extends BasePreferenceContro
super.displayPreference(screen);
mPreference = (SeekBarPreference) screen.findPreference(
KEY_AUTO_BATTERY_SEEK_BAR);
mPreference.setContinuousUpdates(true);
updatePreference(mPreference);
}
@@ -96,6 +99,24 @@ public class AutoBatterySeekBarPreferenceController extends BasePreferenceContro
@VisibleForTesting
void updatePreference(Preference preference) {
final ContentResolver contentResolver = mContext.getContentResolver();
// Override the max value with LOW_POWER_MODE_TRIGGER_LEVEL_MAX, if set.
final int maxLevel = Settings.Global.getInt(contentResolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 0);
if (maxLevel > 0) {
if (!(preference instanceof SeekBarPreference)) {
Log.e(TAG, "Unexpected preference class: " + preference.getClass());
} else {
final SeekBarPreference seekBarPreference = (SeekBarPreference) preference;
if (maxLevel < seekBarPreference.getMin()) {
Log.e(TAG, "LOW_POWER_MODE_TRIGGER_LEVEL_MAX too low; ignored.");
} else {
seekBarPreference.setMax(maxLevel);
}
}
}
// Set the current value.
final int level = Settings.Global.getInt(contentResolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, mDefWarnLevel);
if (level == 0) {
@@ -109,7 +130,7 @@ public class AutoBatterySeekBarPreferenceController extends BasePreferenceContro
}
/**
* Observer that listens to change from {@link Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL}
* Observer that listens to change from {@link Settings.Global#LOW_POWER_MODE_TRIGGER_LEVEL}
*/
private final class AutoBatterySaverSettingObserver extends ContentObserver {
private final Uri mUri = Settings.Global.getUriFor(

View File

@@ -20,9 +20,12 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.ArraySet;
import com.android.settings.fuelgauge.anomaly.Anomaly;
import java.util.Objects;
/**
* Model class stores app info(e.g. package name, type..) that used in battery tip
*/
@@ -32,13 +35,13 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
* Anomaly type of the app
* @see Anomaly.AnomalyType
*/
public final int anomalyType;
public final ArraySet<Integer> anomalyTypes;
public final long screenOnTimeMs;
public final int uid;
private AppInfo(AppInfo.Builder builder) {
packageName = builder.mPackageName;
anomalyType = builder.mAnomalyType;
anomalyTypes = builder.mAnomalyTypes;
screenOnTimeMs = builder.mScreenOnTimeMs;
uid = builder.mUid;
}
@@ -46,7 +49,7 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
@VisibleForTesting
AppInfo(Parcel in) {
packageName = in.readString();
anomalyType = in.readInt();
anomalyTypes = (ArraySet<Integer>) in.readArraySet(null /* loader */);
screenOnTimeMs = in.readLong();
uid = in.readInt();
}
@@ -64,14 +67,14 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(packageName);
dest.writeInt(anomalyType);
dest.writeArraySet(anomalyTypes);
dest.writeLong(screenOnTimeMs);
dest.writeInt(uid);
}
@Override
public String toString() {
return "packageName=" + packageName + ",anomalyType=" + anomalyType + ",screenTime="
return "packageName=" + packageName + ",anomalyTypes=" + anomalyTypes + ",screenTime="
+ screenOnTimeMs;
}
@@ -85,7 +88,7 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
}
AppInfo other = (AppInfo) obj;
return anomalyType == other.anomalyType
return Objects.equals(anomalyTypes, other.anomalyTypes)
&& uid == other.uid
&& screenOnTimeMs == other.screenOnTimeMs
&& TextUtils.equals(packageName, other.packageName);
@@ -102,13 +105,13 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
};
public static final class Builder {
private int mAnomalyType;
private ArraySet<Integer> mAnomalyTypes = new ArraySet<>();
private String mPackageName;
private long mScreenOnTimeMs;
private int mUid;
public Builder setAnomalyType(int type) {
mAnomalyType = type;
public Builder addAnomalyType(int type) {
mAnomalyTypes.add(type);
return this;
}

View File

@@ -32,10 +32,12 @@ import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import android.util.ArrayMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Database manager for battery data. Now it only contains anomaly data stored in {@link AppInfo}.
@@ -88,20 +90,30 @@ public class BatteryDatabaseManager {
try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) {
final String[] projection = {PACKAGE_NAME, ANOMALY_TYPE, UID};
final String orderBy = AnomalyDatabaseHelper.AnomalyColumns.TIME_STAMP_MS + " DESC";
final Map<Integer, AppInfo.Builder> mAppInfoBuilders = new ArrayMap<>();
final String selection = TIME_STAMP_MS + " > ? AND " + ANOMALY_STATE + " = ? ";
final String[] selectionArgs = new String[]{String.valueOf(timestampMsAfter),
String.valueOf(state)};
try (Cursor cursor = db.query(TABLE_ANOMALY, projection,
TIME_STAMP_MS + " > ? AND " + ANOMALY_STATE + " = ? ",
new String[]{String.valueOf(timestampMsAfter), String.valueOf(state)}, null,
null, orderBy)) {
try (Cursor cursor = db.query(TABLE_ANOMALY, projection, selection, selectionArgs,
null /* groupBy */, null /* having */, orderBy)) {
while (cursor.moveToNext()) {
AppInfo appInfo = new AppInfo.Builder()
.setPackageName(cursor.getString(cursor.getColumnIndex(PACKAGE_NAME)))
.setAnomalyType(cursor.getInt(cursor.getColumnIndex(ANOMALY_TYPE)))
.setUid(cursor.getInt(cursor.getColumnIndex(UID)))
.build();
appInfos.add(appInfo);
final int uid = cursor.getInt(cursor.getColumnIndex(UID));
if (!mAppInfoBuilders.containsKey(uid)) {
final AppInfo.Builder builder = new AppInfo.Builder()
.setUid(uid)
.setPackageName(
cursor.getString(cursor.getColumnIndex(PACKAGE_NAME)));
mAppInfoBuilders.put(uid, builder);
}
mAppInfoBuilders.get(uid).addAnomalyType(
cursor.getInt(cursor.getColumnIndex(ANOMALY_TYPE)));
}
}
for (Integer uid : mAppInfoBuilders.keySet()) {
appInfos.add(mAppInfoBuilders.get(uid).build());
}
}
return appInfos;

View File

@@ -104,9 +104,7 @@ public class BatteryTipPreferenceController extends BasePreferenceController {
final Preference preference = batteryTip.buildPreference(mPrefContext);
mBatteryTipMap.put(preference.getKey(), batteryTip);
mPreferenceGroup.addPreference(preference);
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_BATTERY_TIP_SHOWN,
batteryTip.getType());
batteryTip.log(mContext, mMetricsFeatureProvider);
break;
}
}

View File

@@ -16,8 +16,6 @@
package com.android.settings.fuelgauge.batterytip;
import android.app.Fragment;
import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.fuelgauge.batterytip.actions.BatterySaverAction;

View File

@@ -25,6 +25,8 @@ import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.util.SparseIntArray;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -123,6 +125,11 @@ public abstract class BatteryTip implements Comparable<BatteryTip>, Parcelable {
*/
public abstract void updateState(BatteryTip tip);
/**
* Log the battery tip
*/
public abstract void log(Context context, MetricsFeatureProvider metricsFeatureProvider);
public Preference buildPreference(Context context) {
Preference preference = new Preference(context);

View File

@@ -19,7 +19,9 @@ package com.android.settings.fuelgauge.batterytip.tips;
import android.content.Context;
import android.os.Parcel;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to show early warning if battery couldn't make to usual charging time
@@ -75,6 +77,12 @@ public class EarlyWarningTip extends BatteryTip {
mPowerSaveModeOn = earlyWarningTip.mPowerSaveModeOn;
}
@Override
public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_EARLY_WARNING_TIP,
mState);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);

View File

@@ -21,9 +21,11 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.StringUtil;
import java.util.List;
@@ -78,6 +80,18 @@ public class HighUsageTip extends BatteryTip {
mState = tip.mState;
}
@Override
public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP,
mState);
for (int i = 0, size = mHighUsageAppList.size(); i < size; i++) {
final AppInfo appInfo = mHighUsageAppList.get(i);
metricsFeatureProvider.action(context,
MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP_LIST,
appInfo.packageName);
}
}
public long getScreenTimeMs() {
return mScreenTimeMs;
}

View File

@@ -20,7 +20,9 @@ import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to show current battery life is short
@@ -55,6 +57,12 @@ public class LowBatteryTip extends BatteryTip {
mState = tip.mState;
}
@Override
public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_LOW_BATTERY_TIP,
mState);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new LowBatteryTip(in);

View File

@@ -19,11 +19,14 @@ package com.android.settings.fuelgauge.batterytip.tips;
import android.content.Context;
import android.content.res.Resources;
import android.os.Parcel;
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import java.util.ArrayList;
import java.util.List;
@@ -93,6 +96,24 @@ public class RestrictAppTip extends BatteryTip {
}
}
@Override
public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP,
mState);
if (mState == StateType.NEW) {
for (int i = 0, size = mRestrictAppList.size(); i < size; i++) {
final AppInfo appInfo = mRestrictAppList.get(i);
for (Integer anomalyType : appInfo.anomalyTypes) {
metricsFeatureProvider.action(context,
MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP_LIST,
appInfo.packageName,
Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, anomalyType));
}
}
}
}
public List<AppInfo> getRestrictAppList() {
return mRestrictAppList;
}

View File

@@ -20,7 +20,9 @@ import android.content.Context;
import android.os.Parcel;
import android.provider.Settings;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to suggest turn on smart battery if it is not on
@@ -55,6 +57,12 @@ public class SmartBatteryTip extends BatteryTip {
mState = tip.mState;
}
@Override
public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_SMART_BATTERY_TIP,
mState);
}
public static final Creator CREATOR = new Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new SmartBatteryTip(in);

View File

@@ -20,7 +20,9 @@ import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to show general summary about battery life
@@ -55,6 +57,12 @@ public class SummaryTip extends BatteryTip {
mState = tip.mState;
}
@Override
public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_SUMMARY_TIP,
mState);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new SummaryTip(in);

View File

@@ -21,6 +21,7 @@ import android.os.Parcel;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to suggest user to remove app restriction. This is the empty tip and it is only used in
@@ -66,6 +67,11 @@ public class UnrestrictAppTip extends BatteryTip {
mState = tip.mState;
}
@Override
public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
// Do nothing
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);

View File

@@ -88,6 +88,10 @@ public class ZenModeBackend {
return mZenMode;
}
protected boolean isVisualEffectSuppressed(int visualEffect) {
return (mPolicy.suppressedVisualEffects & visualEffect) != 0;
}
protected boolean isPriorityCategoryEnabled(int categoryType) {
return (mPolicy.priorityCategories & categoryType) != 0;
}
@@ -117,8 +121,8 @@ public class ZenModeBackend {
return SOURCE_NONE;
}
protected void saveVisualEffectsPolicy(int category, boolean canBypass) {
int suppressedEffects = getNewSuppressedEffects(!canBypass, category);
protected void saveVisualEffectsPolicy(int category, boolean suppress) {
int suppressedEffects = getNewSuppressedEffects(suppress, category);
savePolicy(mPolicy.priorityCategories, mPolicy.priorityCallSenders,
mPolicy.priorityMessageSenders, suppressedEffects);
}

View File

@@ -49,8 +49,6 @@ public class ZenModeBehaviorSettings extends ZenModeSettingsBase implements Inde
controllers.add(new ZenModeRepeatCallersPreferenceController(context, lifecycle,
context.getResources().getInteger(com.android.internal.R.integer
.config_zen_repeat_callers_threshold)));
controllers.add(new ZenModeScreenOnPreferenceController(context, lifecycle));
controllers.add(new ZenModeScreenOffPreferenceController(context, lifecycle));
controllers.add(new ZenModeBehaviorFooterPreferenceController(context, lifecycle));
return controllers;
}
@@ -85,15 +83,6 @@ public class ZenModeBehaviorSettings extends ZenModeSettingsBase implements Inde
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context);
keys.add(ZenModeAlarmsPreferenceController.KEY);
keys.add(ZenModeMediaPreferenceController.KEY);
keys.add(ZenModeEventsPreferenceController.KEY);
keys.add(ZenModeRemindersPreferenceController.KEY);
keys.add(ZenModeMessagesPreferenceController.KEY);
keys.add(ZenModeCallsPreferenceController.KEY);
keys.add(ZenModeRepeatCallersPreferenceController.KEY);
keys.add(ZenModeScreenOnPreferenceController.KEY);
keys.add(ZenModeScreenOffPreferenceController.KEY);
return keys;
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2018 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.settings.notification;
import android.content.Context;
import android.support.v7.preference.Preference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeBlockedEffectsPreferenceController extends
AbstractZenModePreferenceController implements PreferenceControllerMixin {
protected static final String KEY = "zen_mode_block_effects_settings";
private final ZenModeSettings.SummaryBuilder mSummaryBuilder;
public ZenModeBlockedEffectsPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public CharSequence getSummary() {
return mSummaryBuilder.getBlockedEffectsSummary(getPolicy());
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright (C) 2018 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.settings.notification;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import android.content.Context;
import android.provider.SearchIndexableResource;
import android.support.v7.preference.CheckBoxPreference;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
import java.util.List;
public class ZenModeBlockedEffectsSettings extends ZenModeSettingsBase implements Indexable {
@Override
public void onResume() {
super.onResume();
CheckBoxPreference soundPreference =
(CheckBoxPreference) getPreferenceScreen().findPreference("zen_effect_sound");
if (soundPreference != null) {
soundPreference.setChecked(true);
}
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context, getLifecycle());
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
"zen_effect_intent", SUPPRESSED_EFFECT_FULL_SCREEN_INTENT,
MetricsEvent.ACTION_ZEN_BLOCK_FULL_SCREEN_INTENTS, null));
controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
"zen_effect_light", SUPPRESSED_EFFECT_LIGHTS,
MetricsEvent.ACTION_ZEN_BLOCK_LIGHT, null));
controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
"zen_effect_peek", SUPPRESSED_EFFECT_PEEK,
MetricsEvent.ACTION_ZEN_BLOCK_PEEK, null));
controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
"zen_effect_status", SUPPRESSED_EFFECT_STATUS_BAR,
MetricsEvent.ACTION_ZEN_BLOCK_STATUS,
new int[] {SUPPRESSED_EFFECT_NOTIFICATION_LIST}));
controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
"zen_effect_badge", SUPPRESSED_EFFECT_BADGE,
MetricsEvent.ACTION_ZEN_BLOCK_BADGE, null));
controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
"zen_effect_ambient", SUPPRESSED_EFFECT_AMBIENT,
MetricsEvent.ACTION_ZEN_BLOCK_AMBIENT, null));
controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
"zen_effect_list", SUPPRESSED_EFFECT_NOTIFICATION_LIST,
MetricsEvent.ACTION_ZEN_BLOCK_NOTIFICATION_LIST, null));
return controllers;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.zen_mode_block_settings;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.ZEN_WHAT_TO_BLOCK;
}
/**
* For Search.
*/
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final ArrayList<SearchIndexableResource> result = new ArrayList<>();
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.zen_mode_block_settings;
result.add(sir);
return result;
}
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context);
return keys;
}
@Override
public List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context, null);
}
};
}

View File

@@ -1,66 +0,0 @@
/*
* Copyright (C) 2017 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.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeScreenOffPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener {
protected static final String KEY = "zen_mode_screen_off";
public ZenModeScreenOffPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
SwitchPreference pref = (SwitchPreference) preference;
pref.setChecked(mBackend.isEffectAllowed(Policy.SUPPRESSED_EFFECT_SCREEN_OFF));
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean bypass = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) {
Log.d(TAG, "onPrefChange allowWhenScreenOff=" + bypass);
}
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_WHEN_SCREEN_OFF, bypass);
mBackend.saveVisualEffectsPolicy(Policy.SUPPRESSED_EFFECT_SCREEN_OFF, bypass);
return true;
}
}

View File

@@ -1,65 +0,0 @@
/*
* Copyright (C) 2017 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.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeScreenOnPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener {
protected static final String KEY = "zen_mode_screen_on";
public ZenModeScreenOnPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
SwitchPreference pref = (SwitchPreference) preference;
pref.setChecked(mBackend.isEffectAllowed(Policy.SUPPRESSED_EFFECT_SCREEN_ON));
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean bypass = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allowWhenScreenOn="
+ bypass);
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_WHEN_SCREEN_ON, bypass);
mBackend.saveVisualEffectsPolicy(Policy.SUPPRESSED_EFFECT_SCREEN_ON, bypass);
return true;
}
}

View File

@@ -63,6 +63,7 @@ public class ZenModeSettings extends ZenModeSettingsBase {
Lifecycle lifecycle, FragmentManager fragmentManager) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeBehaviorPreferenceController(context, lifecycle));
controllers.add(new ZenModeBlockedEffectsPreferenceController(context, lifecycle));
controllers.add(new ZenModeAutomationPreferenceController(context));
controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle));
@@ -137,6 +138,18 @@ public class ZenModeSettings extends ZenModeSettingsBase {
}
}
String getBlockedEffectsSummary(Policy policy) {
if (policy.suppressedVisualEffects == 0) {
return mContext.getResources().getString(
R.string.zen_mode_block_effect_summary_sound);
} else if (Policy.areAllVisualEffectsSuppressed(policy.suppressedVisualEffects)) {
return mContext.getResources().getString(
R.string.zen_mode_block_effect_summary_all);
}
return mContext.getResources().getString(
R.string.zen_mode_block_effect_summary_some);
}
String getAutomaticRulesSummary() {
final int count = getEnabledAutomaticRulesCount();
return count == 0 ? mContext.getString(R.string.zen_mode_settings_summary_off)

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2018 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.settings.notification;
import android.content.Context;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeVisEffectPreferenceController
extends AbstractZenModePreferenceController
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
protected final String mKey;
protected final int mEffect;
protected final int mMetricsCategory;
// if any of these effects are suppressed, this effect must be too
protected final int[] mParentSuppressedEffects;
private PreferenceScreen mScreen;
public ZenModeVisEffectPreferenceController(Context context, Lifecycle lifecycle, String key,
int visualEffect, int metricsCategory, int[] parentSuppressedEffects) {
super(context, key, lifecycle);
mKey = key;
mEffect = visualEffect;
mMetricsCategory = metricsCategory;
mParentSuppressedEffects = parentSuppressedEffects;
}
@Override
public String getPreferenceKey() {
return mKey;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void displayPreference(PreferenceScreen screen) {
mScreen = screen;
super.displayPreference(screen);
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
boolean suppressed = mBackend.isVisualEffectSuppressed(mEffect);
boolean parentSuppressed = false;
if (mParentSuppressedEffects != null) {
for (int parentEffect : mParentSuppressedEffects) {
parentSuppressed |= mBackend.isVisualEffectSuppressed(parentEffect);
}
}
if (parentSuppressed) {
((CheckBoxPreference) preference).setChecked(parentSuppressed);
onPreferenceChange(preference, parentSuppressed);
preference.setEnabled(false);
} else {
preference.setEnabled(true);
((CheckBoxPreference) preference).setChecked(suppressed);
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean suppressEffect = (Boolean) newValue;
mMetricsFeatureProvider.action(mContext, mMetricsCategory, suppressEffect);
mBackend.saveVisualEffectsPolicy(mEffect, suppressEffect);
return true;
}
}

View File

@@ -20,7 +20,10 @@ import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
@@ -54,16 +57,20 @@ public class SetupChooseLockPattern extends ChooseLockPattern {
public static class SetupChooseLockPatternFragment extends ChooseLockPatternFragment
implements ChooseLockTypeDialogFragment.OnLockTypeSelectedListener {
@Nullable
private Button mOptionsButton;
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
if (!getResources().getBoolean(R.bool.config_lock_pattern_minimal_ui)) {
Button optionsButton = view.findViewById(R.id.screen_lock_options);
optionsButton.setVisibility(View.VISIBLE);
optionsButton.setOnClickListener((btn) ->
mOptionsButton = view.findViewById(R.id.screen_lock_options);
mOptionsButton.setOnClickListener((btn) ->
ChooseLockTypeDialogFragment.newInstance(mUserId)
.show(getChildFragmentManager(), null));
}
return view;
}
@Override
@@ -84,6 +91,16 @@ public class SetupChooseLockPattern extends ChooseLockPattern {
}
}
@Override
protected void updateStage(Stage stage) {
super.updateStage(stage);
if (!getResources().getBoolean(R.bool.config_lock_pattern_minimal_ui)
&& mOptionsButton != null) {
mOptionsButton.setVisibility(
stage == Stage.Introduction ? View.VISIBLE : View.INVISIBLE);
}
}
@Override
public void handleLeftButton() {
SetupSkipDialog dialog = SetupSkipDialog.newInstance(

View File

@@ -74,6 +74,7 @@ import com.android.settings.notification.ConfigureNotificationSettings;
import com.android.settings.notification.SoundSettings;
import com.android.settings.notification.ZenModeAutomationSettings;
import com.android.settings.notification.ZenModeBehaviorSettings;
import com.android.settings.notification.ZenModeBlockedEffectsSettings;
import com.android.settings.notification.ZenModeSettings;
import com.android.settings.print.PrintSettingsFragment;
import com.android.settings.security.EncryptionAndCredential;
@@ -175,6 +176,7 @@ public class SearchIndexableResourcesImpl implements SearchIndexableResources {
addIndex(UsbDetailsFragment.class);
addIndex(WifiDisplaySettings.class);
addIndex(ZenModeBehaviorSettings.class);
addIndex(ZenModeBlockedEffectsSettings.class);
addIndex(ZenModeAutomationSettings.class);
addIndex(NightDisplaySettings.class);
addIndex(SmartBatterySettings.class);

View File

@@ -18,6 +18,10 @@ package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.content.pm.PackageManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -28,6 +32,7 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
@@ -38,15 +43,18 @@ public class BluetoothFilesPreferenceControllerTest {
private Context mContext;
private BluetoothFilesPreferenceController mController;
private Preference mPreference;
@Mock
private PackageManager mPackageManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mContext = spy(RuntimeEnvironment.application);
mController = new BluetoothFilesPreferenceController(mContext);
mPreference = new Preference(mContext);
mPreference.setKey(BluetoothFilesPreferenceController.KEY_RECEIVED_FILES);
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
}
@Test

View File

@@ -15,6 +15,8 @@
*/
package com.android.settings.connecteddevice;
import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
@@ -24,6 +26,7 @@ import static org.mockito.Mockito.when;
import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceManager;
@@ -58,6 +61,8 @@ public class ConnectedDeviceGroupControllerTest {
private PreferenceScreen mPreferenceScreen;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceManager mPreferenceManager;
@Mock
private PackageManager mPackageManager;
private PreferenceGroup mPreferenceGroup;
private Context mContext;
@@ -70,7 +75,7 @@ public class ConnectedDeviceGroupControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mContext = spy(RuntimeEnvironment.application);
mPreference = new Preference(mContext);
mPreference.setKey(PREFERENCE_KEY_1);
mLifecycleOwner = () -> mLifecycle;
@@ -78,6 +83,8 @@ public class ConnectedDeviceGroupControllerTest {
mPreferenceGroup = spy(new PreferenceScreen(mContext, null));
when(mPreferenceGroup.getPreferenceManager()).thenReturn(mPreferenceManager);
doReturn(mContext).when(mDashboardFragment).getContext();
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
mConnectedDeviceGroupController = new ConnectedDeviceGroupController(mDashboardFragment,
mLifecycle, mConnectedBluetoothDeviceUpdater, mConnectedUsbDeviceUpdater);
@@ -134,4 +141,12 @@ public class ConnectedDeviceGroupControllerTest {
verify(mConnectedBluetoothDeviceUpdater).unregisterCallback();
verify(mConnectedUsbDeviceUpdater).unregisterCallback();
}
@Test
public void testGetAvailabilityStatus_noBluetoothFeature_returnUnSupported() {
doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
assertThat(mConnectedDeviceGroupController.getAvailabilityStatus()).isEqualTo(
DISABLED_UNSUPPORTED);
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2018 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.settings.connecteddevice;
import static android.arch.lifecycle.Lifecycle.Event.ON_START;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
public class SavedDeviceGroupControllerTest {
private static final String PREFERENCE_KEY_1 = "pref_key_1";
@Mock
private DashboardFragment mDashboardFragment;
@Mock
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
@Mock
private PreferenceScreen mPreferenceScreen;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceManager mPreferenceManager;
@Mock
private PackageManager mPackageManager;
private PreferenceGroup mPreferenceGroup;
private Context mContext;
private Preference mPreference;
private SavedDeviceGroupController mConnectedDeviceGroupController;
private LifecycleOwner mLifecycleOwner;
private Lifecycle mLifecycle;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
doReturn(mContext).when(mDashboardFragment).getContext();
doReturn(mPackageManager).when(mContext).getPackageManager();
}
@Test
public void constructor_noBluetoothFeature_shouldNotRegisterCallback() {
doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
mConnectedDeviceGroupController = new SavedDeviceGroupController(mDashboardFragment,
mLifecycle, mBluetoothDeviceUpdater);
assertThat(mConnectedDeviceGroupController.getAvailabilityStatus()).isEqualTo(
DISABLED_UNSUPPORTED);
mLifecycle.handleLifecycleEvent(ON_START);
verify(mBluetoothDeviceUpdater, never()).registerCallback();
}
@Test
public void constructor_hasBluetoothFeature_shouldRegisterCallback() {
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
mConnectedDeviceGroupController = new SavedDeviceGroupController(mDashboardFragment,
mLifecycle, mBluetoothDeviceUpdater);
assertThat(mConnectedDeviceGroupController.getAvailabilityStatus()).isEqualTo(
AVAILABLE);
mLifecycle.handleLifecycleEvent(ON_START);
verify(mBluetoothDeviceUpdater).registerCallback();
}
}

View File

@@ -48,6 +48,7 @@ import com.android.settingslib.suggestions.SuggestionControllerMixin;
import com.android.settingslib.utils.IconCache;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -142,6 +143,7 @@ public class SuggestionAdapterTest {
.isEqualTo(R.layout.suggestion_tile_with_button);
}
@Ignore
@Test
public void onBindViewHolder_shouldLog() {
final View view = spy(LayoutInflater.from(mContext).inflate(
@@ -162,6 +164,7 @@ public class SuggestionAdapterTest {
mOneSuggestion.get(0).getId());
}
@Ignore
@Test
public void onBindViewHolder_itemViewShouldHandleClick()
throws PendingIntent.CanceledException {
@@ -175,6 +178,7 @@ public class SuggestionAdapterTest {
verify(suggestions.get(0).getPendingIntent()).send();
}
@Ignore
@Test
public void onBindViewHolder_hasButton_buttonShouldHandleClick()
throws PendingIntent.CanceledException {
@@ -201,6 +205,7 @@ public class SuggestionAdapterTest {
verify(pendingIntent).send();
}
@Ignore
@Test
public void getSuggestions_shouldReturnSuggestionWhenMatch() {
final List<Suggestion> suggestions = makeSuggestions("pkg1");
@@ -209,6 +214,7 @@ public class SuggestionAdapterTest {
assertThat(mSuggestionAdapter.getSuggestion(0)).isNotNull();
}
@Ignore
@Test
public void onBindViewHolder_closeButtonShouldHandleClick()
throws PendingIntent.CanceledException {
@@ -230,13 +236,43 @@ public class SuggestionAdapterTest {
verify(callback).onSuggestionClosed(suggestion);
}
@Ignore
@Test
public void onBindViewHolder_shouldTintIcon() throws PendingIntent.CanceledException {
public void onBindViewHolder_iconNotTintable_shouldNotTintIcon()
throws PendingIntent.CanceledException {
final Icon icon = mock(Icon.class);
final Suggestion suggestion = new Suggestion.Builder("pkg1")
.setPendingIntent(mock(PendingIntent.class))
.setIcon(icon)
.build();
final List<Suggestion> suggestions = new ArrayList<>();
suggestions.add(suggestion);
mSuggestionAdapter = new SuggestionAdapter(mActivity, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));
IconCache cache = mock(IconCache.class);
final Drawable drawable = mock(Drawable.class);
when(cache.getIcon(icon)).thenReturn(drawable);
ReflectionHelpers.setField(mSuggestionAdapter, "mCache", cache);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
verify(drawable, never()).setTint(anyInt());
}
@Ignore
@Test
public void onBindViewHolder_iconTintable_shouldTintIcon()
throws PendingIntent.CanceledException {
final Icon icon = mock(Icon.class);
final int FLAG_ICON_TINTABLE = 1 << 1;
final Suggestion suggestion = new Suggestion.Builder("pkg1")
.setPendingIntent(mock(PendingIntent.class))
.setIcon(icon)
.setFlags(FLAG_ICON_TINTABLE)
.build();
final List<Suggestion> suggestions = new ArrayList<>();
suggestions.add(suggestion);
@@ -260,6 +296,7 @@ public class SuggestionAdapterTest {
verify(drawable).setTint(colorAccent);
}
@Ignore
@Test
public void onBindViewHolder_closeButtonShouldHaveContentDescription()
throws PendingIntent.CanceledException {
@@ -273,6 +310,7 @@ public class SuggestionAdapterTest {
.isNotNull();
}
@Ignore
@Test
public void setCardLayout_twoCards_shouldSetCardWidthToHalfScreenMinusPadding() {
final List<Suggestion> suggestions = makeSuggestions("pkg1");

View File

@@ -119,5 +119,11 @@ public class BaseTimeZoneInfoPickerTest {
public Context getContext() {
return RuntimeEnvironment.application;
}
@Override
public int getMetricsCategory() {
// the metric id doesn't matter in test
return 1;
}
}
}

View File

@@ -16,41 +16,78 @@
package com.android.settings.datetime.timezone;
import android.content.Context;
import com.android.settings.datetime.timezone.BaseTimeZoneAdapter.AdapterItem;
import com.android.settings.datetime.timezone.model.TimeZoneData;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import libcore.util.CountryZonesFinder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
public class FixedOffsetPickerTest {
private CountryZonesFinder mFinder;
@Before
public void setUp() {
List regionList = Collections.emptyList();
mFinder = mock(CountryZonesFinder.class);
when(mFinder.lookupAllCountryIsoCodes()).thenReturn(regionList);
}
@Test
public void getAllTimeZoneInfos_containsUtcAndGmtZones() {
List regionList = Collections.emptyList();
CountryZonesFinder finder = mock(CountryZonesFinder.class);
when(finder.lookupAllCountryIsoCodes()).thenReturn(regionList);
FixedOffsetPicker picker = new FixedOffsetPicker() {
@Override
protected Locale getLocale() {
return Locale.US;
}
};
List<TimeZoneInfo> infos = picker.getAllTimeZoneInfos(new TimeZoneData(finder));
TestFixedOffsetPicker picker = new TestFixedOffsetPicker();
List<TimeZoneInfo> infos = picker.getAllTimeZoneInfos(new TimeZoneData(mFinder));
List<String> tzIds = infos.stream().map(info -> info.getId()).collect(Collectors.toList());
tzIds.contains("Etc/Utc");
tzIds.contains("Etc/GMT-12");
tzIds.contains("Etc/GMT+14");
assertThat(tzIds).contains("Etc/UTC");
assertThat(tzIds).contains("Etc/GMT-14"); // Etc/GMT-14 means GMT+14:00
assertThat(tzIds).contains("Etc/GMT+12"); // Etc/GMT+14 means GMT-12:00
}
@Test
public void createAdapter_verifyTitleAndOffset() {
TestFixedOffsetPicker picker = new TestFixedOffsetPicker();
BaseTimeZoneAdapter adapter = picker.createAdapter(new TimeZoneData(mFinder));
assertThat(adapter.getItemCount()).isEqualTo(12 + 1 + 14); // 27 GMT offsets from -12 to +14
AdapterItem utc = adapter.getItem(0);
assertThat(utc.getTitle().toString()).isEqualTo("Coordinated Universal Time");
assertThat(utc.getSummary().toString()).isEqualTo("GMT+00:00");
AdapterItem gmtMinus12 = adapter.getItem(1);
assertThat(gmtMinus12.getTitle().toString()).isEqualTo("GMT-12:00");
assertThat(gmtMinus12.getSummary().toString()).isEmpty();
}
public static class TestFixedOffsetPicker extends FixedOffsetPicker {
// Make the method public
@Override
public BaseTimeZoneAdapter createAdapter(TimeZoneData timeZoneData) {
return super.createAdapter(timeZoneData);
}
@Override
protected Locale getLocale() {
return Locale.US;
}
@Override
public Context getContext() {
return RuntimeEnvironment.application;
}
}
}

View File

@@ -40,10 +40,9 @@ public class FixedOffsetPreferenceControllerTest {
}
@Test
public void updateState_matchTimeZoneSummary() {
public void updateState_GmtMinus8_matchTimeZoneSummary() {
TimeZoneInfo fixedOffsetZone = new TimeZoneInfo.Builder(
TimeZone.getFrozenTimeZone("Etc/GMT-8"))
.setExemplarLocation("Los Angeles")
.setGmtOffset("GMT-08:00")
.setItemId(0)
.build();
@@ -52,6 +51,21 @@ public class FixedOffsetPreferenceControllerTest {
controller.setTimeZoneInfo(fixedOffsetZone);
controller.updateState(preference);
assertThat(preference.getSummary()).isEqualTo("GMT-08:00");
}
@Test
public void updateState_Utc_matchTimeZoneSummary() {
TimeZoneInfo fixedOffsetZone = new TimeZoneInfo.Builder(
TimeZone.getFrozenTimeZone("Etc/UTC"))
.setStandardName("Coordinated Universal Time")
.setGmtOffset("GMT+00:00")
.setItemId(0)
.build();
Preference preference = new Preference(mActivity);
FixedOffsetPreferenceController controller = new FixedOffsetPreferenceController(mActivity);
controller.setTimeZoneInfo(fixedOffsetZone);
controller.updateState(preference);
assertThat(preference.getSummary().toString())
.isEqualTo("Coordinated Universal Time (GMT+00:00)");
}
}

View File

@@ -40,7 +40,6 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class BatteryDatabaseManagerTest {
private static String PACKAGE_NAME_NEW = "com.android.app1";
private static int UID_NEW = 345;
private static int TYPE_NEW = 1;
@@ -53,6 +52,9 @@ public class BatteryDatabaseManagerTest {
private Context mContext;
private BatteryDatabaseManager mBatteryDatabaseManager;
private AppInfo mNewAppInfo;
private AppInfo mOldAppInfo;
private AppInfo mCombinedAppInfo;
@Before
public void setUp() {
@@ -60,6 +62,23 @@ public class BatteryDatabaseManagerTest {
mContext = RuntimeEnvironment.application;
mBatteryDatabaseManager = spy(BatteryDatabaseManager.getInstance(mContext));
mNewAppInfo = new AppInfo.Builder()
.setUid(UID_NEW)
.setPackageName(PACKAGE_NAME_NEW)
.addAnomalyType(TYPE_NEW)
.build();
mOldAppInfo = new AppInfo.Builder()
.setUid(UID_OLD)
.setPackageName(PACKAGE_NAME_OLD)
.addAnomalyType(TYPE_OLD)
.build();
mCombinedAppInfo = new AppInfo.Builder()
.setUid(UID_NEW)
.setPackageName(PACKAGE_NAME_NEW)
.addAnomalyType(TYPE_NEW)
.addAnomalyType(TYPE_OLD)
.build();
}
@After
@@ -77,23 +96,19 @@ public class BatteryDatabaseManagerTest {
// In database, it contains two record
List<AppInfo> totalAppInfos = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */,
AnomalyDatabaseHelper.State.NEW);
assertThat(totalAppInfos).hasSize(2);
assertAppInfo(totalAppInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
assertAppInfo(totalAppInfos.get(1), UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD);
assertThat(totalAppInfos).containsExactly(mNewAppInfo, mOldAppInfo);
// Only one record shows up if we query by timestamp
List<AppInfo> appInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
AnomalyDatabaseHelper.State.NEW);
assertThat(appInfos).hasSize(1);
assertAppInfo(appInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
assertThat(appInfos).containsExactly(mNewAppInfo);
mBatteryDatabaseManager.deleteAllAnomaliesBeforeTimeStamp(ONE_DAY_BEFORE);
// The obsolete record is removed from database
List<AppInfo> appInfos1 = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */,
AnomalyDatabaseHelper.State.NEW);
assertThat(appInfos1).hasSize(1);
assertAppInfo(appInfos1.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
assertThat(appInfos1).containsExactly(mNewAppInfo);
}
@Test
@@ -113,19 +128,24 @@ public class BatteryDatabaseManagerTest {
// The state of PACKAGE_NAME_NEW is still new
List<AppInfo> newAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
AnomalyDatabaseHelper.State.NEW);
assertThat(newAppInfos).hasSize(1);
assertAppInfo(newAppInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
assertThat(newAppInfos).containsExactly(mNewAppInfo);
// The state of PACKAGE_NAME_OLD is changed to handled
List<AppInfo> handledAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
AnomalyDatabaseHelper.State.HANDLED);
assertThat(handledAppInfos).hasSize(1);
assertAppInfo(handledAppInfos.get(0), UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD);
assertThat(handledAppInfos).containsExactly(mOldAppInfo);
}
private void assertAppInfo(final AppInfo appInfo, int uid, String packageName, int type) {
assertThat(appInfo.packageName).isEqualTo(packageName);
assertThat(appInfo.anomalyType).isEqualTo(type);
assertThat(appInfo.uid).isEqualTo(uid);
@Test
public void testQueryAnomalies_removeDuplicateByUid() {
mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW,
AnomalyDatabaseHelper.State.NEW, NOW);
mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_OLD,
AnomalyDatabaseHelper.State.NEW, NOW);
// Only contain one AppInfo with multiple types
List<AppInfo> newAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
AnomalyDatabaseHelper.State.NEW);
assertThat(newAppInfos).containsExactly(mCombinedAppInfo);
}
}

View File

@@ -99,4 +99,24 @@ public class AutoBatterySeekBarPreferenceControllerTest {
assertThat(Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isEqualTo(TRIGGER_LEVEL);
}
@Test
public void testOnPreferenceChange_changeMax() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 50);
mController.updateState(mPreference);
assertThat(mPreference.getMax()).isEqualTo(50);
}
@Test
public void testOnPreferenceChange_noChangeMax() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 0);
mController.updateState(mPreference);
assertThat(mPreference.getMax()).isEqualTo(100);
}
}

View File

@@ -36,7 +36,8 @@ import java.util.List;
public class AppInfoTest {
private static final String PACKAGE_NAME = "com.android.app";
private static final int ANOMALY_TYPE = Anomaly.AnomalyType.WAKE_LOCK;
private static final int TYPE_WAKELOCK = Anomaly.AnomalyType.WAKE_LOCK;
private static final int TYPE_WAKEUP = Anomaly.AnomalyType.WAKEUP_ALARM;
private static final long SCREEN_TIME_MS = DateUtils.HOUR_IN_MILLIS;
private static final int UID = 3452;
@@ -46,7 +47,8 @@ public class AppInfoTest {
public void setUp() {
mAppInfo = new AppInfo.Builder()
.setPackageName(PACKAGE_NAME)
.setAnomalyType(ANOMALY_TYPE)
.addAnomalyType(TYPE_WAKELOCK)
.addAnomalyType(TYPE_WAKEUP)
.setScreenOnTimeMs(SCREEN_TIME_MS)
.setUid(UID)
.build();
@@ -61,7 +63,7 @@ public class AppInfoTest {
final AppInfo appInfo = new AppInfo(parcel);
assertThat(appInfo.packageName).isEqualTo(PACKAGE_NAME);
assertThat(appInfo.anomalyType).isEqualTo(ANOMALY_TYPE);
assertThat(appInfo.anomalyTypes).containsExactly(TYPE_WAKELOCK, TYPE_WAKEUP);
assertThat(appInfo.screenOnTimeMs).isEqualTo(SCREEN_TIME_MS);
assertThat(appInfo.uid).isEqualTo(UID);
}
@@ -70,7 +72,7 @@ public class AppInfoTest {
public void testCompareTo_hasCorrectOrder() {
final AppInfo appInfo = new AppInfo.Builder()
.setPackageName(PACKAGE_NAME)
.setAnomalyType(ANOMALY_TYPE)
.addAnomalyType(TYPE_WAKELOCK)
.setScreenOnTimeMs(SCREEN_TIME_MS + 100)
.build();
@@ -85,7 +87,7 @@ public class AppInfoTest {
@Test
public void testBuilder() {
assertThat(mAppInfo.packageName).isEqualTo(PACKAGE_NAME);
assertThat(mAppInfo.anomalyType).isEqualTo(ANOMALY_TYPE);
assertThat(mAppInfo.anomalyTypes).containsExactly(TYPE_WAKELOCK, TYPE_WAKEUP);
assertThat(mAppInfo.screenOnTimeMs).isEqualTo(SCREEN_TIME_MS);
assertThat(mAppInfo.uid).isEqualTo(UID);
}

View File

@@ -17,6 +17,7 @@
package com.android.settings.fuelgauge.batterytip;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.robolectric.Shadows.shadowOf;
@@ -29,7 +30,6 @@ import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -67,7 +67,6 @@ public class BatteryTipDialogFragmentTest {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
FakeFeatureFactory.setupForTest();
List<AppInfo> highUsageTips = new ArrayList<>();
final AppInfo appInfo = new AppInfo.Builder()
@@ -102,7 +101,7 @@ public class BatteryTipDialogFragmentTest {
ShadowAlertDialog shadowDialog = shadowOf(dialog);
assertThat(shadowDialog.getMessage())
.isEqualTo(mContext.getString(R.string.battery_tip_dialog_message, "1h"));
.isEqualTo(mContext.getString(R.string.battery_tip_dialog_message, "1h"));
}
@Test
@@ -116,7 +115,7 @@ public class BatteryTipDialogFragmentTest {
assertThat(shadowDialog.getTitle()).isEqualTo("Restrict app?");
assertThat(shadowDialog.getMessage())
.isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
.isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
}
@Test
@@ -134,7 +133,7 @@ public class BatteryTipDialogFragmentTest {
assertThat(shadowDialog.getTitle()).isEqualTo("Restrict 2 apps?");
assertThat(shadowDialog.getMessage())
.isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
.isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
assertThat(shadowDialog.getView()).isNotNull();
}
@@ -150,6 +149,6 @@ public class BatteryTipDialogFragmentTest {
assertThat(shadowDialog.getTitle()).isEqualTo("Remove restriction for app?");
assertThat(shadowDialog.getMessage())
.isEqualTo(mContext.getString(R.string.battery_tip_unrestrict_app_dialog_message));
.isEqualTo(mContext.getString(R.string.battery_tip_unrestrict_app_dialog_message));
}
}

View File

@@ -119,9 +119,9 @@ public class BatteryTipPreferenceControllerTest {
public void testUpdateBatteryTips_logBatteryTip() {
mBatteryTipPreferenceController.updateBatteryTips(mOldBatteryTips);
verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
eq(MetricsProto.MetricsEvent.ACTION_BATTERY_TIP_SHOWN),
eq(BatteryTip.TipType.SUMMARY));
verify(mFeatureFactory.metricsFeatureProvider).action(mContext,
MetricsProto.MetricsEvent.ACTION_SUMMARY_TIP,
BatteryTip.StateType.NEW);
}
@Test

View File

@@ -25,6 +25,7 @@ import android.support.v7.preference.Preference;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
@@ -122,6 +123,11 @@ public class BatteryTipTest {
// do nothing
}
@Override
public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
// do nothing
}
public final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new TestBatteryTip(in);

View File

@@ -17,28 +17,38 @@ package com.android.settings.fuelgauge.batterytip.tips;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.os.Parcel;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class EarlyWarningTipTest {
@Mock
private MetricsFeatureProvider mMetricsFeatureProvider;
private Context mContext;
private EarlyWarningTip mEarlyWarningTip;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mEarlyWarningTip =
new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerSaveModeOn */);
new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerSaveModeOn */);
}
@Test
@@ -55,7 +65,7 @@ public class EarlyWarningTipTest {
@Test
public void testInfo_stateNew_displayPowerModeInfo() {
final EarlyWarningTip tip =
new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerModeOn */);
new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerModeOn */);
assertThat(tip.getTitle(mContext)).isEqualTo("Turn on Low Battery Mode");
assertThat(tip.getSummary(mContext)).isEqualTo("Extend your battery life");
@@ -65,7 +75,7 @@ public class EarlyWarningTipTest {
@Test
public void testInfo_stateHandled_displayPowerModeHandledInfo() {
final EarlyWarningTip tip =
new EarlyWarningTip(BatteryTip.StateType.HANDLED, false /* powerModeOn */);
new EarlyWarningTip(BatteryTip.StateType.HANDLED, false /* powerModeOn */);
assertThat(tip.getTitle(mContext)).isEqualTo("Low Battery Mode is on");
assertThat(tip.getSummary(mContext)).isEqualTo("Some features are limited");
@@ -75,7 +85,7 @@ public class EarlyWarningTipTest {
@Test
public void testUpdate_powerModeTurnedOn_typeBecomeHandled() {
final EarlyWarningTip nextTip =
new EarlyWarningTip(BatteryTip.StateType.INVISIBLE, true /* powerModeOn */);
new EarlyWarningTip(BatteryTip.StateType.INVISIBLE, true /* powerModeOn */);
mEarlyWarningTip.updateState(nextTip);
@@ -115,4 +125,12 @@ public class EarlyWarningTipTest {
assertThat(earlyWarningTip.getState()).isEqualTo(BatteryTip.StateType.INVISIBLE);
}
@Test
public void testLog() {
mEarlyWarningTip.log(mContext, mMetricsFeatureProvider);
verify(mMetricsFeatureProvider).action(mContext,
MetricsProto.MetricsEvent.ACTION_EARLY_WARNING_TIP, BatteryTip.StateType.NEW);
}
}

View File

@@ -17,16 +17,22 @@ package com.android.settings.fuelgauge.batterytip.tips;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.os.Parcel;
import android.text.format.DateUtils;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
@@ -38,14 +44,17 @@ public class HighUsageTipTest {
private static final String PACKAGE_NAME = "com.android.app";
private static final long SCREEN_TIME = 30 * DateUtils.MINUTE_IN_MILLIS;
@Mock
private MetricsFeatureProvider mMetricsFeatureProvider;
private Context mContext;
private HighUsageTip mBatteryTip;
private List<AppInfo> mUsageAppList;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mUsageAppList = new ArrayList<>();
mUsageAppList.add(new AppInfo.Builder()
.setPackageName(PACKAGE_NAME)
@@ -77,6 +86,18 @@ public class HighUsageTipTest {
@Test
public void toString_containsAppData() {
assertThat(mBatteryTip.toString()).isEqualTo(
"type=2 state=0 { packageName=com.android.app,anomalyType=0,screenTime=1800000 }");
"type=2 state=0 { packageName=com.android.app,anomalyTypes={},screenTime=1800000 "
+ "}");
}
@Test
public void testLog_logAppInfo() {
mBatteryTip.log(mContext, mMetricsFeatureProvider);
verify(mMetricsFeatureProvider).action(mContext,
MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP, BatteryTip.StateType.NEW);
verify(mMetricsFeatureProvider).action(mContext,
MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP_LIST,
PACKAGE_NAME);
}
}

View File

@@ -16,16 +16,25 @@
package com.android.settings.fuelgauge.batterytip.tips;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Parcel;
import android.util.Pair;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
@@ -39,9 +48,10 @@ import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
public class RestrictAppTipTest {
private static final String PACKAGE_NAME = "com.android.app";
private static final String DISPLAY_NAME = "app";
private static final int ANOMALY_WAKEUP = 0;
private static final int ANOMALY_WAKELOCK = 1;
private Context mContext;
private RestrictAppTip mNewBatteryTip;
@@ -52,6 +62,8 @@ public class RestrictAppTipTest {
private ApplicationInfo mApplicationInfo;
@Mock
private PackageManager mPackageManager;
@Mock
private MetricsFeatureProvider mMetricsFeatureProvider;
@Before
public void setUp() throws Exception {
@@ -64,7 +76,11 @@ public class RestrictAppTipTest {
doReturn(DISPLAY_NAME).when(mApplicationInfo).loadLabel(mPackageManager);
mUsageAppList = new ArrayList<>();
mUsageAppList.add(new AppInfo.Builder().setPackageName(PACKAGE_NAME).build());
mUsageAppList.add(new AppInfo.Builder()
.setPackageName(PACKAGE_NAME)
.addAnomalyType(ANOMALY_WAKEUP)
.addAnomalyType(ANOMALY_WAKELOCK)
.build());
mNewBatteryTip = new RestrictAppTip(BatteryTip.StateType.NEW, mUsageAppList);
mHandledBatteryTip = new RestrictAppTip(BatteryTip.StateType.HANDLED, mUsageAppList);
mInvisibleBatteryTip = new RestrictAppTip(BatteryTip.StateType.INVISIBLE, mUsageAppList);
@@ -125,6 +141,32 @@ public class RestrictAppTipTest {
@Test
public void toString_containsAppData() {
assertThat(mNewBatteryTip.toString()).isEqualTo(
"type=1 state=0 { packageName=com.android.app,anomalyType=0,screenTime=0 }");
"type=1 state=0 { packageName=com.android.app,anomalyTypes={0, 1},screenTime=0 }");
}
@Test
public void testLog_stateNew_logAppInfo() {
mNewBatteryTip.log(mContext, mMetricsFeatureProvider);
verify(mMetricsFeatureProvider).action(mContext,
MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP, BatteryTip.StateType.NEW);
verify(mMetricsFeatureProvider).action(mContext,
MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP_LIST,
PACKAGE_NAME,
Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, ANOMALY_WAKEUP));
verify(mMetricsFeatureProvider).action(mContext,
MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP_LIST,
PACKAGE_NAME,
Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, ANOMALY_WAKELOCK));
}
@Test
public void testLog_stateHandled_doNotLogAppInfo() {
mHandledBatteryTip.log(mContext, mMetricsFeatureProvider);
verify(mMetricsFeatureProvider).action(mContext,
MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP, BatteryTip.StateType.HANDLED);
verify(mMetricsFeatureProvider, never()).action(any(), anyInt(), anyString(), any());
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2018 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.settings.fuelgauge.batterytip.tips;
import static org.mockito.Mockito.verify;
import android.content.Context;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class SmartBatteryTipTest {
@Mock
private MetricsFeatureProvider mMetricsFeatureProvider;
private Context mContext;
private SmartBatteryTip mSmartBatteryTip;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mSmartBatteryTip = new SmartBatteryTip(BatteryTip.StateType.NEW);
}
@Test
public void testLog() {
mSmartBatteryTip.log(mContext, mMetricsFeatureProvider);
verify(mMetricsFeatureProvider).action(mContext,
MetricsProto.MetricsEvent.ACTION_SMART_BATTERY_TIP, BatteryTip.StateType.NEW);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The Android Open Source Project
* Copyright (C) 2018 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.
@@ -16,13 +16,13 @@
package com.android.settings.notification;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.Context;
import android.support.v14.preference.SwitchPreference;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -37,22 +37,17 @@ import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModeScreenOnPreferenceControllerTest {
public final class ZenModeBlockedEffectsPreferenceControllerTest {
private static final boolean MOCK_PRIORITY_SCREEN_ON_SETTING = false;
private ZenModeScreenOnPreferenceController mController;
@Mock
private ZenModeBackend mBackend;
private ZenModeBlockedEffectsPreferenceController mController;
@Mock
private NotificationManager mNotificationManager;
@Mock
private SwitchPreference mockPref;
@Mock
private NotificationManager.Policy mPolicy;
private Context mContext;
@Mock
private ZenModeBackend mBackend;
@Before
public void setup() {
@@ -63,35 +58,18 @@ public class ZenModeScreenOnPreferenceControllerTest {
mContext = RuntimeEnvironment.application;
when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
mController = new ZenModeScreenOnPreferenceController(mContext, mock(Lifecycle.class));
mController = new ZenModeBlockedEffectsPreferenceController(
mContext, mock(Lifecycle.class));
ReflectionHelpers.setField(mController, "mBackend", mBackend);
}
@Test
public void updateState() {
final SwitchPreference mockPref = mock(SwitchPreference.class);
when(mBackend.isEffectAllowed(NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON))
.thenReturn(MOCK_PRIORITY_SCREEN_ON_SETTING);
mController.updateState(mockPref);
verify(mockPref).setChecked(MOCK_PRIORITY_SCREEN_ON_SETTING);
public void testIsAvailable() {
assertTrue(mController.isAvailable());
}
@Test
public void onPreferenceChanged_EnableScreenOn() {
boolean allow = true;
mController.onPreferenceChange(mockPref, allow);
verify(mBackend)
.saveVisualEffectsPolicy(NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON, allow);
public void testHasSummary() {
assertNotNull(mController.getSummary());
}
@Test
public void onPreferenceChanged_DisableScreenOn() {
boolean allow = false;
mController.onPreferenceChange(mockPref, allow);
verify(mBackend)
.saveVisualEffectsPolicy(NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON, allow);
}
}
}

View File

@@ -1,96 +0,0 @@
/*
* Copyright (C) 2017 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.settings.notification;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.Context;
import android.support.v14.preference.SwitchPreference;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModeScreenOffPreferenceControllerTest {
private static final boolean MOCK_PRIORITY_SCREEN_OFF_SETTING = false;
private ZenModeScreenOffPreferenceController mController;
@Mock
private ZenModeBackend mBackend;
@Mock
private NotificationManager mNotificationManager;
@Mock
private SwitchPreference mockPref;
@Mock
private NotificationManager.Policy mPolicy;
private Context mContext;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
mContext = shadowApplication.getApplicationContext();
when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
mController = new ZenModeScreenOffPreferenceController(mContext, mock(Lifecycle.class));
ReflectionHelpers.setField(mController, "mBackend", mBackend);
}
@Test
public void updateState() {
final SwitchPreference mockPref = mock(SwitchPreference.class);
when(mBackend.isEffectAllowed(NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF))
.thenReturn(MOCK_PRIORITY_SCREEN_OFF_SETTING);
mController.updateState(mockPref);
verify(mockPref).setChecked(MOCK_PRIORITY_SCREEN_OFF_SETTING);
}
@Test
public void onPreferenceChanged_EnableScreenOff() {
boolean allow = true;
mController.onPreferenceChange(mockPref, allow);
verify(mBackend).saveVisualEffectsPolicy(
NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF, allow);
}
@Test
public void onPreferenceChanged_DisableScreenOff() {
boolean allow = false;
mController.onPreferenceChange(mockPref, allow);
verify(mBackend).saveVisualEffectsPolicy(
NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF, allow);
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2018 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.settings.notification;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.Context;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModeVisEffectPreferenceControllerTest {
private ZenModeVisEffectPreferenceController mController;
@Mock
private ZenModeBackend mBackend;
@Mock
private CheckBoxPreference mockPref;
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
@Mock
private PreferenceScreen mScreen;
@Mock NotificationManager mNotificationManager;
private static final String PREF_KEY = "main_pref";
private static final int PREF_METRICS = 1;
private static final int PARENT_EFFECT1 = SUPPRESSED_EFFECT_BADGE;
private static final int PARENT_EFFECT2 = SUPPRESSED_EFFECT_NOTIFICATION_LIST;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
mContext = shadowApplication.getApplicationContext();
mFeatureFactory = FakeFeatureFactory.setupForTest();
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
when(mNotificationManager.getNotificationPolicy()).thenReturn(
mock(NotificationManager.Policy.class));
mController = new ZenModeVisEffectPreferenceController(mContext, mock(Lifecycle.class),
PREF_KEY, SUPPRESSED_EFFECT_PEEK, PREF_METRICS, null);
ReflectionHelpers.setField(mController, "mBackend", mBackend);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
mController.displayPreference(mScreen);
}
@Test
public void updateState_notChecked() {
when(mBackend.isVisualEffectSuppressed(SUPPRESSED_EFFECT_PEEK)).thenReturn(false);
mController.updateState(mockPref);
verify(mockPref).setChecked(false);
verify(mockPref).setEnabled(true);
}
@Test
public void updateState_checked() {
when(mBackend.isVisualEffectSuppressed(SUPPRESSED_EFFECT_PEEK)).thenReturn(true);
mController.updateState(mockPref);
verify(mockPref).setChecked(true);
verify(mockPref).setEnabled(true);
}
@Test
public void updateState_checkedFalse_parentChecked() {
mController = new ZenModeVisEffectPreferenceController(mContext, mock(Lifecycle.class),
PREF_KEY, SUPPRESSED_EFFECT_PEEK, PREF_METRICS,
new int[] {PARENT_EFFECT1, PARENT_EFFECT2});
ReflectionHelpers.setField(mController, "mBackend", mBackend);
when(mBackend.isVisualEffectSuppressed(SUPPRESSED_EFFECT_PEEK)).thenReturn(false);
when(mBackend.isVisualEffectSuppressed(PARENT_EFFECT1)).thenReturn(false);
when(mBackend.isVisualEffectSuppressed(PARENT_EFFECT2)).thenReturn(true);
mController.updateState(mockPref);
verify(mockPref).setChecked(true);
verify(mockPref).setEnabled(false);
verify(mBackend, times(1)).saveVisualEffectsPolicy(SUPPRESSED_EFFECT_PEEK, true);
}
@Test
public void updateState_checkedFalse_parentNotChecked() {
mController = new ZenModeVisEffectPreferenceController(mContext, mock(Lifecycle.class),
PREF_KEY, SUPPRESSED_EFFECT_PEEK, PREF_METRICS,
new int[] {PARENT_EFFECT1, PARENT_EFFECT2});
ReflectionHelpers.setField(mController, "mBackend", mBackend);
when(mBackend.isVisualEffectSuppressed(SUPPRESSED_EFFECT_PEEK)).thenReturn(false);
when(mBackend.isVisualEffectSuppressed(PARENT_EFFECT1)).thenReturn(false);
when(mBackend.isVisualEffectSuppressed(PARENT_EFFECT2)).thenReturn(false);
mController.updateState(mockPref);
verify(mockPref).setChecked(false);
verify(mockPref).setEnabled(true);
verify(mBackend, never()).saveVisualEffectsPolicy(SUPPRESSED_EFFECT_PEEK, true);
}
@Test
public void onPreferenceChanged_checkedFalse() {
mController.onPreferenceChange(mockPref, false);
verify(mBackend).saveVisualEffectsPolicy(SUPPRESSED_EFFECT_PEEK, false);
verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
eq(PREF_METRICS),
eq(false));
}
@Test
public void onPreferenceChanged_checkedTrue() {
mController.onPreferenceChange(mockPref, true);
verify(mBackend).saveVisualEffectsPolicy(SUPPRESSED_EFFECT_PEEK, true);
verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
eq(PREF_METRICS),
eq(true));
}
}

View File

@@ -27,6 +27,7 @@ import android.os.UserHandle;
import android.view.View;
import android.widget.Button;
import com.android.internal.widget.LockPatternView;
import com.android.settings.R;
import com.android.settings.SetupRedactionInterstitial;
import com.android.settings.password.ChooseLockPattern.ChooseLockPatternFragment;
@@ -44,6 +45,11 @@ import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowAlertDialog;
import org.robolectric.shadows.ShadowPackageManager;
import org.robolectric.util.ReflectionHelpers;
import org.robolectric.util.ReflectionHelpers.ClassParameter;
import java.util.Collections;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {
@@ -83,6 +89,17 @@ public class SetupChooseLockPatternTest {
assertThat(componentEnabled).isEqualTo(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
}
@Config(qualifiers = "sw400dp")
@Test
public void selectPattern_shouldHideOptionsButton() {
Button button = mActivity.findViewById(R.id.screen_lock_options);
assertThat(button).isNotNull();
assertThat(button.getVisibility()).isEqualTo(View.VISIBLE);
LockPatternView lockPatternView = mActivity.findViewById(R.id.lockPattern);
ReflectionHelpers.callInstanceMethod(lockPatternView, "notifyPatternDetected");
}
@Config(qualifiers = "sw400dp")
@Test
public void sw400dp_shouldShowScreenLockOptions() {