(android.content.Context, android.util.AttributeSet, int);
10 | }
11 |
12 | # Keep annotated classes or class members.
13 | -keep @androidx.annotation.Keep class *
14 | -keepclassmembers class * {
15 | @androidx.annotation.Keep *;
16 | }
17 |
--------------------------------------------------------------------------------
/res/drawable/ic_outline_pan_tool_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/res/layout/preference_labeled_slider.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
28 |
29 |
39 |
40 |
49 |
50 |
55 |
56 |
63 |
64 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/res/layout/settings_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/res/values-ast-rES/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Serviciu «Active Edge»
19 | Active Edge
20 | Sí / %1$s
21 | Non
22 | Active Edge, berbesu, xestu, asistente, asistir, apertar, apertamientu, presión
23 | Apertar el teléfonu pa facer una aición
24 | Pa facer dalguna aición, apierta y suelta los berbesos del teléfonu cierca de la parte baxera
25 | Sensibilidá
26 | Presión llixera
27 | Presión fuerte
28 | Permitir cola pantalla apagada
29 | Pue aumentar les aiciones accidentales
30 | L\'aición actual bloquia la opción
31 | Al apertar
32 | Facer una captura de pantalla
33 | Abrir l\'asistente
34 | Abrir la cámara
35 | Abrir el menú d\'apagáu
36 | Desactivar el soníu de les llamaes y los avisos
37 | Prender/apagar la llinterna
38 | Prender/apagar la pantalla
39 |
40 |
--------------------------------------------------------------------------------
/res/values-az/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Aktiv Edge Xidməti
19 | Aktiv Edge
20 | Açıq / %1$s
21 | Bağlı
22 | Aktiv Edge, sıxma, künc, jest, kömək, köməkçi
23 | Əməliyyatı icra etmək üçün telefonu sıxın
24 | Bir əməliyyat icra etmək üçün telefonun aşağı hissəsinin kənarlarını sıxıb buraxın
25 | Həssaslıq
26 | Yüngül sıxma
27 | Möhkəm sıxma
28 | Ekran sönülü olanda icazə ver
29 | Yanlış tətikləyiciləri artıra bilər
30 | Hazırkı əməliyyat tərəfindən əngəlləndi
31 | Sıxanda
32 | Ekran şəklini çək
33 | Köməkçini aç
34 | Kameranı aç
35 | Güc menyusunu aç
36 | Zəngləri və bildirişləri səssizə al
37 | Fənəri yandır/söndür
38 | Ekranı aç/bağla
39 |
40 |
--------------------------------------------------------------------------------
/res/values-bn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | সক্রিয় এজ সার্ভিস
19 | সক্রিয় এজ
20 | চালু / %1$s
21 | বন্ধ
22 | সক্রিয় এজ, স্কুইজ, এজ, জেসচার, অ্যাসিস্ট, অ্যাসিস্ট্যান্ট
23 | ক্রিয়া সম্পাদনের জন্য ফোন স্কুইজ করুন
24 | ক্রিয়া সম্পাদনের জন্য ফোনের নিচের অংশে স্কুইজ করে ছেড়ে দিন
25 | সেনসিটিভিটি
26 | হালকা স্কুইজ
27 | দৃঢ় স্কুইজ
28 | স্ক্রিন বন্ধ অবস্থায় অনুমতি দেন
29 | ভুলে চালু হওয়ার প্রবণতা বেড়ে যেতে পারে
30 | বর্তমান কার্যক্রমে ব্লক করা হয়েছে
31 | স্কুইজ করলে
32 | স্ক্রীনশট নিন
33 | অ্যাসিস্ট্যান্ট খুলুন
34 | ক্যামেরা খুলুন
35 | পাওয়ার মেনু খুলুন
36 | কল এবং বিজ্ঞপ্তি মিউট করুন
37 | ফ্ল্যাশলাইট অন/অফ করুন
38 | স্ক্রীন অন/অফ করুন
39 |
40 |
--------------------------------------------------------------------------------
/res/values-ca/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Servei de l\'Active Edge
19 | Active Edge
20 | Actiu / %1$s
21 | Desactivat
22 | Active Edge, aixafa, vora, gest, ajudar, ajudant
23 | Aixafeu el telèfon per realitzar accions
24 | Per realitzar una acció, aixafeu i deixeu anar els costats del telèfon a prop de la part inferior
25 | Sensibilitat
26 | Aixafat lleuger
27 | Aixafat ferm
28 | Permetre amb la pantalla apagada
29 | Pot augmentar els desencadenants falsos
30 | Bloquejat per l\'acció actual
31 | En aixafar
32 | Fes una captura de pantalla
33 | Obre l\'assistent
34 | Obre la càmera
35 | Obre el menú d\'energia
36 | Silencia les trucades i notificacions
37 | Llanterna encesa/apagada
38 | Pantalla encesa/apagada
39 |
40 |
--------------------------------------------------------------------------------
/res/values-da/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Service For Aktiv Kant
19 | Aktiv Kant
20 | Til / %1$s
21 | Slukket
22 | Aktiv kant, klemme, kant, gestus, assistent, assistent
23 | Klem telefonen for at udføre handling
24 | For at udføre en handling, klem og slip siderne af din telefon nær bunden
25 | Sensitivitet
26 | Let klem
27 | Fast klem
28 | Tillad, når skærmen er slukket
29 | Kan øge falske udløsere
30 | Blokeret af aktuel handling
31 | Ved pres
32 | Tag skærmbillede
33 | Åbn assistent
34 | Åbn kamera
35 | Åbn tænd/sluk-menu
36 | Lydløs opkald og notifikationer
37 | Lommelygte til/fra
38 | Tænd/sluk skærm
39 |
40 |
--------------------------------------------------------------------------------
/res/values-de/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Active Edge-Dienst
19 | Active Edge
20 | Bei / %1$s
21 | Aus
22 | Active Edge, Zusammendrücken, Rand, Geste, Assistent
23 | Gerät zusammendrücken, um eine Aktion auszulösen
24 | Untere Hälfte des Geräts kurz zusammendrücken und loslassen, um eine Aktion auszulösen
25 | Empfindlichkeit
26 | Leicht drücken
27 | Stark drücken
28 | Bei deaktiviertem Bildschirm zulassen
29 | Kann zu Fehlauslösungen führen
30 | Durch die aktuelle Aktion blockiert
31 | Beim Zusammendrücken
32 | Screenshot erstellen
33 | Assistent öffnen
34 | Kamera öffnen
35 | Ein-/Aus-Menü öffnen
36 | Anrufe und Benachrichtigungen stummschalten
37 | Taschenlampe ein-/ausschalten
38 | Bildschirm ein-/ausschalten
39 |
40 |
--------------------------------------------------------------------------------
/res/values-el/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Υπηρεσία Active Edge
19 | Active Edge
20 | Ενεργό / %1$s
21 | Aνενεργό
22 | Active Edge, πίεση, άκρη, χειρονομία, βοήθεια, βοηθός
23 | Πιέστε το τηλέφωνο για να εκτελέσετε ενέργεια
24 | Για να εκτελέσετε μια ενέργεια, πιέστε και απελευθερώστε τις πλευρές του τηλεφώνου σας κοντά στο κάτω μέρος
25 | Ευαισθησία
26 | Ελαφριά συμπίεση
27 | Σφιχτή συμπίεση
28 | Επιτρέπεται όταν η οθόνη είναι απενεργοποιημένη
29 | Μπορεί να αυξήσει τα ψευδή εναύσματα
30 | Αποκλείστηκε από την τρέχουσα ενέργεια
31 | Κατά την πίεση
32 | Λήψη στιγμιότυπου οθόνης
33 | Άνοιγμα βοηθού
34 | Άνοιγμα φωτογραφικής μηχανής
35 | Άνοιγμα μενού απενεργοποίησης
36 | Σίγαση κλήσεων και ειδοποιήσεων
37 | Ενεργοποίηση/απενεργοποίηση φακού
38 | Ενεργοποίηση/απενεργοποίηση οθόνης
39 |
40 |
--------------------------------------------------------------------------------
/res/values-en-rAU/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Active Edge Service
19 | Active Edge
20 | On / %1$s
21 | Off
22 | Active Edge, squeeze, edge, gesture, assist, assistant
23 | Squeeze phone to perform action
24 | To perform an action, squeeze and release the sides of your phone near the bottom
25 | Sensitivity
26 | Light squeeze
27 | Firm squeeze
28 | Allow when screen is off
29 | May increase false triggers
30 | Blocked by current action
31 | On squeeze
32 | Take screenshot
33 | Open assistant
34 | Open camera
35 | Open power menu
36 | Mute calls and notifications
37 | Turn torch on/off
38 | Turn screen on/off
39 |
40 |
--------------------------------------------------------------------------------
/res/values-en-rCA/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Active Edge Service
19 | Active Edge
20 | On / %1$s
21 | Off
22 | Active Edge, squeeze, edge, gesture, assist, assistant
23 | Squeeze phone to perform action
24 | To perform an action, squeeze and release the sides of your phone near the bottom
25 | Sensitivity
26 | Light squeeze
27 | Firm squeeze
28 | Allow when screen is off
29 | May increase false triggers
30 | Blocked by current action
31 | On squeeze
32 | Take screenshot
33 | Open assistant
34 | Open camera
35 | Open power menu
36 | Mute calls and notifications
37 | Turn torch on/off
38 | Turn screen on/off
39 |
40 |
--------------------------------------------------------------------------------
/res/values-en-rGB/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Active Edge Service
19 | Active Edge
20 | On / %1$s
21 | Off
22 | Active Edge, squeeze, edge, gesture, assist, assistant
23 | Squeeze phone to perform action
24 | To perform an action, squeeze and release the sides of your phone near the bottom
25 | Sensitivity
26 | Light squeeze
27 | Firm squeeze
28 | Allow when screen is off
29 | May increase false triggers
30 | Blocked by current action
31 | On squeeze
32 | Take screenshot
33 | Open assistant
34 | Open camera
35 | Open power menu
36 | Mute calls and notifications
37 | Turn torch on/off
38 | Turn screen on/off
39 |
40 |
--------------------------------------------------------------------------------
/res/values-en-rIN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Active Edge Service
19 | Active Edge
20 | On / %1$s
21 | Off
22 | Active Edge, squeeze, edge, gesture, assist, assistant
23 | Squeeze phone to perform action
24 | To perform an action, squeeze and release the sides of your phone near the bottom
25 | Sensitivity
26 | Light squeeze
27 | Firm squeeze
28 | Allow when screen is off
29 | May increase false triggers
30 | Blocked by current action
31 | On squeeze
32 | Take screenshot
33 | Open assistant
34 | Open camera
35 | Open power menu
36 | Mute calls and notifications
37 | Turn torch on/off
38 | Turn screen on/off
39 |
40 |
--------------------------------------------------------------------------------
/res/values-fr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Service Active Edge
19 | Active Edge
20 | Activé / %1$s
21 | Désactivé
22 | Active Edge, pression, bords, gestes, assistance, assistant
23 | Pressez le téléphone pour effectuer une action
24 | Pour effectuer une action, pressez et relâchez les côtés de la partie inférieure de votre téléphone
25 | Sensibilité
26 | Pression légère
27 | Pression ferme
28 | Autoriser lorsque l\'écran est éteint
29 | Augmente le risque de déclenchement involontaire
30 | Bloqué par l\'action en cours
31 | En pressant
32 | Effectuer une capture d\'écran
33 | Ouvrir l\'assistant
34 | Ouvrir l\'appareil photo
35 | Ouvrir le menu marche/arrêt
36 | Mettre les appels et les notifications en sourdine
37 | Allumer/éteindre la lampe torche
38 | Allumer/éteindre l\'écran
39 |
40 |
--------------------------------------------------------------------------------
/res/values-gd/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Seirbheis Active Edge
19 | Active Edge
20 | Air / %1$s
21 | Dheth
22 | Active Edge, squeeze, edge, gesture, assist, assistant, dinn, oir, gluasad, cuidich, chuidiche
23 | Dinn am fòn airson gnìomh a ghabhail
24 | Airson gnìomh a ghabhail, dinn is leig às cliathaichean an fhòn agad faisg air a’ bhonn
25 | Mothalachd
26 | Dinneadh lag
27 | Dinneadh teann
28 | Ceadaich nuair a bhios an sgrìn dheth
29 | Faodaidh seo nithean a chur gu dol gun iarraidh nas trice
30 | Air a bhacadh leis a’ ghnìomh làithreach
31 | Le dinneadh
32 | Tog glacadh-sgrìn
33 | Fosgail an cuidiche
34 | Fosgail an camara
35 | Fosgail clàr-taice na cumhachd
36 | Mùch gairmean is brathan
37 | Cuir an leus air/dheth
38 | Cuir an sgrìn air/dheth
39 |
40 |
--------------------------------------------------------------------------------
/res/values-gl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Servizo de marxe activa
19 | Marxe activa
20 | Activado / %1$s
21 | Desactivado
22 | Marxe activa, premer, marxe, xesto, asistencia, asistente
23 | Premer no teléfono para realizar unha acción
24 | Para realizar unha acción, preme e solta os lados da parte inferior do teléfono
25 | Sensibilidade
26 | Presión leve
27 | Presión firme
28 | Permitir coa pantalla apagada
29 | Pode causar activacións accidentais
30 | Bloqueado pola acción actual
31 | Ao premer
32 | Capturar pantalla
33 | Abrir asistente
34 | Abrir cámara
35 | Abrir menú de activar/desactivar
36 | Silenciar chamadas e notificacións
37 | Lanterna encendida/apagada
38 | Pantalla encendida/apagada
39 |
40 |
--------------------------------------------------------------------------------
/res/values-hu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Aktív készülékszél szolgáltatás
19 | Aktív készülékszélek
20 | %1$s / Be
21 | Ki
22 | Aktív készülékszél, összenyomás, szélek, mozdulatvezérlés, segéd
23 | Művelet a készülékszélek összenyomásával
24 | Művelet végrehajtásához nyomja össze majd engedje el a telefon széleit a telefon alja közelében
25 | Érzékenység
26 | Enyhe összenyomás
27 | Határozott összenyomás
28 | Engedély alvó képernyőn is
29 | Növelheti a hamis indításokat
30 | A jelenlegi művelet blokkolja
31 | Összenyomáskor
32 | Képernyőmentés
33 | Asszisztens-indítás
34 | Kameraindítás
35 | Kikapcsolómenü-megnyitás
36 | Hívások és értesítések elhalkítása
37 | Zseblámpa be/ki
38 | Képernyő ki/bekapcsolása
39 |
40 |
--------------------------------------------------------------------------------
/res/values-in/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Sensitivitas
19 | Izinkan saat layar mati
20 | Buka asisten
21 | Buka kamera
22 | Buka menu daya
23 |
24 |
--------------------------------------------------------------------------------
/res/values-it/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Servizio Active Edge
19 | Active Edge
20 | On / %1$s
21 | Off
22 | Active Edge, stringi, bordi, gesti, assistente, assistenza
23 | Stringi il telefono per attivare una funzione
24 | Per effettuare un\'azione, stringi e rilascia la parte bassa dei lati del telefono
25 | Sensibilità
26 | Pressione leggera
27 | Pressione forte
28 | Permetti quando lo schermo è spento
29 | Potrebbe aumentare le attivazioni involontarie
30 | Bloccato dall\'azione attuale
31 | Quando si stringe
32 | Cattura schermata
33 | Apri l\'assistente
34 | Apri fotocamera
35 | Apri menù di spegnimento
36 | Silenzia chiamate e notifiche
37 | Accendi/spegni torcia
38 | Accendi/spegni lo schermo
39 |
40 |
--------------------------------------------------------------------------------
/res/values-ja/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Active Edge サービス
19 | Active Edge
20 | ON / %1$s
21 | OFF
22 | Active Edge、握る、エッジ、ジェスチャー、アシスト、アシスタント
23 | 端末を握ってアクションを起動
24 | アクションを起動するには、端末のボタン付近の両端を握った後に離してください。
25 | 感度
26 | 軽い握り
27 | 強い握り
28 | 画面消灯中は許可
29 | 誤作動が増えることがあります
30 | 現在の操作でブロックされました
31 | 握った時
32 | スクリーンショットを撮影
33 | アシスタントを開く
34 | カメラを起動
35 | 電源メニューを開く
36 | 着信と通知をミュート
37 | ライトの ON/OFF
38 | 画面を消灯/点灯
39 |
40 |
--------------------------------------------------------------------------------
/res/values-ko/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Active Edge 서비스
19 | Active Edge
20 | 켜짐 / %1$s
21 | 꺼짐
22 | Active Edge, 쥐기, 엣지, 제스처, 조수, 어시스턴트, 도움
23 | 기기 양쪽을 쥐어 작업 실행
24 | 작업을 실행하려면 기기 양쪽의 아랫부분을 쥐었다 놓으세요.
25 | 민감도
26 | 가볍게 쥐기
27 | 단단히 쥐기
28 | 화면이 꺼져 있을 때 허용
29 | 잘못된 동작이 늘어날 수 있습니다.
30 | 이 행동으로 막힘
31 | 쥐었을 때
32 | 화면 캡처
33 | 어시스턴트 열기
34 | 카메라 열기
35 | 전원 메뉴 열기
36 | 전화 및 알림 음소거
37 | 손전등 켜기/끄기
38 | 화면 켜기/끄기
39 |
40 |
--------------------------------------------------------------------------------
/res/values-nl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Actieve Edge Service
19 | Actieve Edge
20 | Aan / %1$s
21 | Uit
22 | Actieve Edge, squeeze, randen, gebaar, helpen, assistent
23 | Knijp in toestel om actie uit te voeren
24 | Om een actie uit te voeren, knijp in de zijkant van je toestel nabij de onderkant
25 | Gevoeligheid
26 | Licht knijpen
27 | Stevig knijpen
28 | Toestaan wanneer het scherm is uitgeschakeld
29 | Kan valse triggers opleveren
30 | Geblokkeerd door huidige actie
31 | Bij knijpen
32 | Maak schermafbeelding
33 | Open assistent
34 | Open camera
35 | Open aan/uit menu
36 | Oproepen en meldingen zonder geluid
37 | Zaklamp aan/uit zetten
38 | Scherm aan/uit zetten
39 |
40 |
--------------------------------------------------------------------------------
/res/values-pt-rBR/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Sensibilidade
19 | Capturar tela
20 | Abrir assistente
21 | Abrir câmera
22 | Silenciar chamadas e notificações
23 | Ligar/desligar a lanterna
24 | Ligar/desligar a tela
25 |
26 |
--------------------------------------------------------------------------------
/res/values-pt-rPT/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Serviço Active Edge
19 | Active Edge
20 | Ligado / %1$s
21 | Desligado
22 | Active Edge, apertar, borda, gesto, assistência, assistente
23 | Apertar o telefone para executar uma ação
24 | Para executar uma ação, aperte e solte os lados do seu telefone perto da parte inferior
25 | Sensibilidade
26 | Aperto ligeiro
27 | Aperto firme
28 | Permitir com ecrã desligado
29 | Pode implicar ativações indesejadas
30 | Bloqueado pela ação atual
31 | Ao apertar
32 | Realizar captura de ecrã
33 | Abrir o Assistente
34 | Abrir câmara
35 | Abrir menu de ligar/desligar
36 | Silenciar chamadas e notificações
37 | Ligar/desligar lanterna
38 | Ligar/desligar ecrã
39 |
40 |
--------------------------------------------------------------------------------
/res/values-ro/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Serviciu Active Edge
19 | Active Edge
20 | Activ / %1$s
21 | Oprit
22 | Active Edge, strângere, margine, gest, asistență, asistent
23 | Strânge telefonul pentru a realiza acțiunea
24 | Pentru a efectua o acțiune, strângeți și eliberați marginile telefonului din partea de jos
25 | Sensibilitate
26 | Strângere ușoară
27 | Strângere fermă
28 | Permite când ecranul este oprit
29 | Poate crește declanșările false
30 | Blocat de acțiunea curentă
31 | La strângere
32 | Captură ecran
33 | Deschide asistentul
34 | Deschide camera
35 | Deschide meniul de alimentare
36 | Pune pe mut apelurile și notificările
37 | Pornește lanterna
38 | Pornește/stinge ecranul
39 |
40 |
--------------------------------------------------------------------------------
/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Служба Active Edge
19 | Active Edge
20 | Вкл. / %1$s
21 | Выкл.
22 | Active Edge, сжатие, edge, жест, помощь, ассистент
23 | Для выполнения действия сожмите телефон
24 | Для выполнения действия сожмите и отпустите боковые стороны телефона в нижней части корпуса.
25 | Чувствительность
26 | Легкое сжатие
27 | Крепкое сжатие
28 | Разрешить при выключенном экране
29 | Может увеличить количество ложных срабатываний
30 | Заблокировано текущим действием
31 | При сжатии
32 | Сделать скриншот
33 | Открыть ассистента
34 | Открыть камеру
35 | Открыть меню питания
36 | Отключить звук звонков и уведомлений
37 | Включить/выключить фонарик
38 | Включить/выключить экран
39 |
40 |
--------------------------------------------------------------------------------
/res/values-sl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Storitev aktivnega roba
19 | Aktivni rob
20 | Vklopljen / %1$s
21 | Izklopljen
22 | Aktivni rob, stisk, rob, poteza, pomoč, pomočnik
23 | Stisnite telefon za izvedbo dejanja
24 | Za izvedbo dejanja, stisnite in izpustite stranici telefona blizu dna
25 | Občutljivost
26 | Nežen stisk
27 | Čvrst stisk
28 | Dovoli, ko je zaslon izklopljen
29 | Lahko poveča lažne sprožitve
30 | Blokirano s trenutnim dejanjem
31 | Ob stisku
32 | Zajemi zaslonsko sliko
33 | Odpri pomočnika
34 | Odpri fotoaparat
35 | Odpri meni izklopa
36 | Utišaj klice in obvestila
37 | Vklopi/izklopi svetilko
38 | Vklopi/izklopi zaslon
39 |
40 |
--------------------------------------------------------------------------------
/res/values-sq/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Shërbimi Edge Aktiv
19 | Edge aktive
20 | Ndezur / %1$s
21 | Fikur
22 | Edge aktive, shtrydhje, Edge, gjest, asistent, asistent
23 | Shtrydhni telefonin për të kryer veprimin
24 | Për të kryer një veprim, shtrydhni dhe lëshoni anët e telefonit tuaj pranë fundit
25 | Ndjeshmëria
26 | Shtrydhje e lehtë
27 | Shtrydhje e fortë
28 | Lejo kur ekrani është i fikur
29 | Mund të rrisë shkaktarët e rremë
30 | Bllokuar nga veprimi aktual
31 | Në shtrydhje
32 | Bëj foto të ekranit
33 | Hap asistentin
34 | Hap kameren
35 | Hapni menunë e energjisë
36 | Hesht thirrjet dhe njoftimet
37 | Ndizni/fikni elektrikun e dorës
38 | Ndizni/fikni ekranin
39 |
40 |
--------------------------------------------------------------------------------
/res/values-th/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | บริการ Active Edge
19 | เมื่อ / %1$s
20 | ปิด
21 | บีบเบาๆ
22 | บีบแน่นๆ
23 | อนุญาตเมื่อจอดับอยู่
24 | เมื่อบีบ
25 | จับภาพหน้าจอ
26 | เปิด assistant
27 | เปิดกล้อง
28 | ปิดเสียงสายเรียกเข้าและการแจ้งเตือน
29 | เปิด/ปิด ไฟฉาย
30 | เปิด/ปิด หน้าจอ
31 |
32 |
--------------------------------------------------------------------------------
/res/values-tr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Aktif Kenar Hizmeti
19 | Aktif Kenar
20 | Açık / %1$s
21 | Kapalı
22 | Active Edge, sıkma, kenar, hareket, yardım, asistan
23 | İşlemi gerçekleştirmek için telefonu sıkın
24 | Bir işlem gerçekleştirmek için telefonun alt kısmının kenarlarını sıkıştırın
25 | Hassasiyet
26 | Hafif sıkma
27 | Sıkı sıkma
28 | Ekran kapalıyken izin ver
29 | Yanlış tetikleyicileri artırabilir
30 | Mevcut işlem tarafından engellendi
31 | Sıkmak
32 | Ekran görüntüsü al
33 | Asistanı aç
34 | Kamerayı aç
35 | Güç menüsünü aç
36 | Çağrıları ve bildirimleri sessize al
37 | El fenerini aç/kapat
38 | Ekranı aç/kapat
39 |
40 |
--------------------------------------------------------------------------------
/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | 边缘压感服务
19 | 边缘压感
20 | 开启/ %1$s
21 | 关闭
22 | 活动边缘、握压、边缘、手势、辅助、助手
23 | 握压手机来执行操作
24 | 要执行操作,请握压并松开靠近底部的手机侧面
25 | 敏感度
26 | 轻轻握压
27 | 用力握压
28 | 屏幕关闭时允许
29 | 可能增加误触
30 | 被当前操作阻止
31 | 握压操作
32 | 截图
33 | 打开助理
34 | 打开相机
35 | 打开电源菜单
36 | 来电及通知静音
37 | 打开/关闭手电筒
38 | 打开/关闭屏幕
39 |
40 |
--------------------------------------------------------------------------------
/res/values-zh-rTW/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | 活動邊緣服務
19 | 活動邊緣
20 | 開啟/%1$s
21 | 關閉
22 | 活動邊緣、擠壓、邊緣、手勢、輔助、助理
23 | 擠壓手機執行動作
24 | 執行動作, 擠壓並釋放近手機底部兩邊
25 | 靈敏度
26 | 輕壓
27 | 硬壓
28 | 當螢幕關閉時允許
29 | 可能會增加誤觸
30 | 被當前動作阻止
31 | 擠壓時
32 | 螢幕擷取畫面
33 | 開啟助理
34 | 開啟相機
35 | 開啟電源選單
36 | 靜音通話和通知
37 | 開啟/關閉手電筒
38 | 開啟/關閉螢幕
39 |
40 |
--------------------------------------------------------------------------------
/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/res/values/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | true
19 | 5
20 | screenshot
21 | true
22 |
23 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | Active Edge Service
19 |
20 |
21 | enabled
22 | sensitivity
23 | action
24 | allow_screen_off
25 | allow_screen_off_action_forced
26 |
27 |
28 |
29 |
30 |
31 | Active Edge
32 | On / %1$s
33 | Off
34 | Active Edge, squeeze, edge, gesture, assist, assistant
35 |
36 |
37 | Squeeze phone to perform action
38 | To perform an action, squeeze and release the sides of your phone near the bottom
39 | Sensitivity
40 | Light squeeze
41 | Firm squeeze
42 | Allow when screen is off
43 | May increase false triggers
44 | Blocked by current action
45 | On squeeze
46 |
47 |
48 | Take screenshot
49 | Open assistant
50 | Open camera
51 | Open power menu
52 | Mute calls and notifications
53 | Turn flashlight on/off
54 | Turn screen on/off
55 |
56 |
57 |
58 | - screenshot
59 | - assistant
60 | - camera
61 | - power_menu
62 | - mute
63 | - flashlight
64 | - screen
65 |
66 |
67 | - @string/action_screenshot_name
68 | - @string/action_assistant_name
69 | - @string/action_camera_name
70 | - @string/action_power_menu_name
71 | - @string/action_mute_name
72 | - @string/action_flashlight_name
73 | - @string/action_screen_name
74 |
75 |
76 |
--------------------------------------------------------------------------------
/res/xml/settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
24 |
25 |
32 |
33 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/com/android/settings/widget/DefaultIndicatorSeekBar.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.settings.widget;
18 |
19 | import android.content.Context;
20 | import android.graphics.Canvas;
21 | import android.graphics.drawable.Drawable;
22 | import android.util.AttributeSet;
23 | import android.widget.SeekBar;
24 |
25 | public class DefaultIndicatorSeekBar extends SeekBar {
26 |
27 | private int mDefaultProgress = -1;
28 |
29 | public DefaultIndicatorSeekBar(Context context) {
30 | super(context);
31 | }
32 |
33 | public DefaultIndicatorSeekBar(Context context, AttributeSet attrs) {
34 | super(context, attrs);
35 | }
36 |
37 | public DefaultIndicatorSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
38 | super(context, attrs, defStyleAttr);
39 | }
40 |
41 | public DefaultIndicatorSeekBar(Context context, AttributeSet attrs, int defStyleAttr,
42 | int defStyleRes) {
43 | super(context, attrs, defStyleAttr, defStyleRes);
44 | }
45 |
46 | /**
47 | * N.B. Only draws the default indicator tick mark, NOT equally spaced tick marks.
48 | */
49 | @Override
50 | protected void drawTickMarks(Canvas canvas) {
51 | if (isEnabled() && mDefaultProgress <= getMax() && mDefaultProgress >= getMin()) {
52 | final Drawable defaultIndicator = getTickMark();
53 |
54 | // Adjust the drawable's bounds to center it at the point where it's drawn.
55 | final int w = defaultIndicator.getIntrinsicWidth();
56 | final int h = defaultIndicator.getIntrinsicHeight();
57 | final int halfW = w >= 0 ? w / 2 : 1;
58 | final int halfH = h >= 0 ? h / 2 : 1;
59 | defaultIndicator.setBounds(-halfW, -halfH, halfW, halfH);
60 |
61 | // This mimics the computation of the thumb position, to get the true "default."
62 | final int availableWidth = getWidth() - mPaddingLeft - mPaddingRight;
63 | final int range = getMax() - getMin();
64 | final float scale = range > 0f ? mDefaultProgress / (float) range : 0f;
65 | final int offset = (int) ((scale * availableWidth) + 0.5f);
66 | final int indicatorPosition = isLayoutRtl() && getMirrorForRtl()
67 | ? availableWidth - offset + mPaddingRight : offset + mPaddingLeft;
68 |
69 | final int saveCount = canvas.save();
70 | canvas.translate(indicatorPosition, getHeight() / 2);
71 | defaultIndicator.draw(canvas);
72 | canvas.restoreToCount(saveCount);
73 | }
74 | }
75 |
76 | /**
77 | * N.B. This sets the default *unadjusted* progress, i.e. in the SeekBar's [0 - max] terms.
78 | */
79 | public void setDefaultProgress(int defaultProgress) {
80 | if (mDefaultProgress != defaultProgress) {
81 | mDefaultProgress = defaultProgress;
82 | invalidate();
83 | }
84 | }
85 |
86 | public int getDefaultProgress() {
87 | return mDefaultProgress;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/com/android/settings/widget/LabeledSeekBarPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.settings.widget;
18 |
19 | import android.content.Context;
20 | import android.content.res.TypedArray;
21 | import android.graphics.drawable.Drawable;
22 | import android.util.AttributeSet;
23 | import android.widget.SeekBar;
24 | import android.widget.TextView;
25 |
26 | import androidx.core.content.res.TypedArrayUtils;
27 | import androidx.preference.PreferenceViewHolder;
28 |
29 | import org.protonaosp.elmyra.R;
30 |
31 | /** A slider preference with left and right labels **/
32 | public class LabeledSeekBarPreference extends SeekBarPreference {
33 |
34 | private final int mTextStartId;
35 | private final int mTextEndId;
36 | private final int mTickMarkId;
37 | private OnPreferenceChangeListener mStopListener;
38 |
39 | public LabeledSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
40 | int defStyleRes) {
41 |
42 | super(context, attrs, defStyleAttr, defStyleRes);
43 | setLayoutResource(R.layout.preference_labeled_slider);
44 |
45 | final TypedArray styledAttrs = context.obtainStyledAttributes(attrs,
46 | R.styleable.LabeledSeekBarPreference);
47 | mTextStartId = styledAttrs.getResourceId(
48 | R.styleable.LabeledSeekBarPreference_textStart,
49 | R.string.summary_placeholder);
50 | mTextEndId = styledAttrs.getResourceId(
51 | R.styleable.LabeledSeekBarPreference_textEnd,
52 | R.string.summary_placeholder);
53 | mTickMarkId = styledAttrs.getResourceId(
54 | R.styleable.LabeledSeekBarPreference_tickMark, /* defValue= */ 0);
55 | styledAttrs.recycle();
56 | }
57 |
58 | public LabeledSeekBarPreference(Context context, AttributeSet attrs) {
59 | this(context, attrs, TypedArrayUtils.getAttr(context,
60 | androidx.preference.R.attr.seekBarPreferenceStyle,
61 | com.android.internal.R.attr.seekBarPreferenceStyle), 0);
62 | }
63 |
64 | @Override
65 | public void onBindViewHolder(PreferenceViewHolder holder) {
66 | super.onBindViewHolder(holder);
67 |
68 | final TextView startText = (TextView) holder.findViewById(android.R.id.text1);
69 | final TextView endText = (TextView) holder.findViewById(android.R.id.text2);
70 | startText.setText(mTextStartId);
71 | endText.setText(mTextEndId);
72 |
73 | if (mTickMarkId != 0) {
74 | final Drawable tickMark = getContext().getDrawable(mTickMarkId);
75 | final SeekBar seekBar = (SeekBar) holder.findViewById(
76 | com.android.internal.R.id.seekbar);
77 | seekBar.setTickMark(tickMark);
78 | }
79 | }
80 |
81 | public void setOnPreferenceChangeStopListener(OnPreferenceChangeListener listener) {
82 | mStopListener = listener;
83 | }
84 |
85 | @Override
86 | public void onStopTrackingTouch(SeekBar seekBar) {
87 | super.onStopTrackingTouch(seekBar);
88 |
89 | if (mStopListener != null) {
90 | mStopListener.onPreferenceChange(this, seekBar.getProgress());
91 | }
92 | }
93 | }
94 |
95 |
--------------------------------------------------------------------------------
/src/com/android/settings/widget/SeekBarPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.settings.widget;
18 |
19 | import static android.view.HapticFeedbackConstants.CLOCK_TICK;
20 |
21 | import android.content.Context;
22 | import android.content.res.TypedArray;
23 | import android.os.Parcel;
24 | import android.os.Parcelable;
25 | import android.text.TextUtils;
26 | import android.util.AttributeSet;
27 | import android.view.KeyEvent;
28 | import android.view.View;
29 | import android.view.accessibility.AccessibilityNodeInfo;
30 | import android.widget.SeekBar;
31 | import android.widget.SeekBar.OnSeekBarChangeListener;
32 |
33 | import androidx.core.content.res.TypedArrayUtils;
34 | import androidx.preference.PreferenceViewHolder;
35 |
36 | import com.android.settingslib.RestrictedPreference;
37 |
38 | /**
39 | * Based on android.preference.SeekBarPreference, but uses support preference as base.
40 | */
41 | public class SeekBarPreference extends RestrictedPreference
42 | implements OnSeekBarChangeListener, View.OnKeyListener {
43 |
44 | public static final int HAPTIC_FEEDBACK_MODE_NONE = 0;
45 | public static final int HAPTIC_FEEDBACK_MODE_ON_TICKS = 1;
46 | public static final int HAPTIC_FEEDBACK_MODE_ON_ENDS = 2;
47 |
48 | private int mProgress;
49 | private int mMax;
50 | private int mMin;
51 | private boolean mTrackingTouch;
52 |
53 | private boolean mContinuousUpdates;
54 | private int mHapticFeedbackMode = HAPTIC_FEEDBACK_MODE_NONE;
55 | private int mDefaultProgress = -1;
56 |
57 | private SeekBar mSeekBar;
58 | private boolean mShouldBlink;
59 | private int mAccessibilityRangeInfoType = AccessibilityNodeInfo.RangeInfo.RANGE_TYPE_INT;
60 | private CharSequence mOverrideSeekBarStateDescription;
61 | private CharSequence mSeekBarContentDescription;
62 | private CharSequence mSeekBarStateDescription;
63 |
64 | public SeekBarPreference(
65 | Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
66 | super(context, attrs, defStyleAttr, defStyleRes);
67 |
68 | TypedArray a = context.obtainStyledAttributes(
69 | attrs, com.android.internal.R.styleable.ProgressBar, defStyleAttr, defStyleRes);
70 | setMax(a.getInt(com.android.internal.R.styleable.ProgressBar_max, mMax));
71 | setMin(a.getInt(com.android.internal.R.styleable.ProgressBar_min, mMin));
72 | a.recycle();
73 |
74 | a = context.obtainStyledAttributes(attrs,
75 | com.android.internal.R.styleable.SeekBarPreference, defStyleAttr, defStyleRes);
76 | final int layoutResId = a.getResourceId(
77 | com.android.internal.R.styleable.SeekBarPreference_layout,
78 | com.android.internal.R.layout.preference_widget_seekbar);
79 | a.recycle();
80 |
81 | a = context.obtainStyledAttributes(
82 | attrs, com.android.internal.R.styleable.Preference, defStyleAttr, defStyleRes);
83 | final boolean isSelectable = a.getBoolean(
84 | org.protonaosp.elmyra.R.styleable.Preference_android_selectable, false);
85 | setSelectable(isSelectable);
86 | a.recycle();
87 |
88 | setLayoutResource(layoutResId);
89 | }
90 |
91 | public SeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
92 | this(context, attrs, defStyleAttr, 0);
93 | }
94 |
95 | public SeekBarPreference(Context context, AttributeSet attrs) {
96 | this(context, attrs, TypedArrayUtils.getAttr(context,
97 | androidx.preference.R.attr.seekBarPreferenceStyle,
98 | com.android.internal.R.attr.seekBarPreferenceStyle));
99 | }
100 |
101 | public SeekBarPreference(Context context) {
102 | this(context, null);
103 | }
104 |
105 | public void setShouldBlink(boolean shouldBlink) {
106 | mShouldBlink = shouldBlink;
107 | notifyChanged();
108 | }
109 |
110 | @Override
111 | public boolean isSelectable() {
112 | if(isDisabledByAdmin()) {
113 | return true;
114 | } else {
115 | return super.isSelectable();
116 | }
117 | }
118 |
119 | @Override
120 | public void onBindViewHolder(PreferenceViewHolder view) {
121 | super.onBindViewHolder(view);
122 | view.itemView.setOnKeyListener(this);
123 | mSeekBar = (SeekBar) view.findViewById(
124 | com.android.internal.R.id.seekbar);
125 | mSeekBar.setOnSeekBarChangeListener(this);
126 | mSeekBar.setMax(mMax);
127 | mSeekBar.setMin(mMin);
128 | mSeekBar.setProgress(mProgress);
129 | mSeekBar.setEnabled(isEnabled());
130 | final CharSequence title = getTitle();
131 | if (!TextUtils.isEmpty(mSeekBarContentDescription)) {
132 | mSeekBar.setContentDescription(mSeekBarContentDescription);
133 | } else if (!TextUtils.isEmpty(title)) {
134 | mSeekBar.setContentDescription(title);
135 | }
136 | if (!TextUtils.isEmpty(mSeekBarStateDescription)) {
137 | mSeekBar.setStateDescription(mSeekBarStateDescription);
138 | }
139 | if (mSeekBar instanceof DefaultIndicatorSeekBar) {
140 | ((DefaultIndicatorSeekBar) mSeekBar).setDefaultProgress(mDefaultProgress);
141 | }
142 | if (mShouldBlink) {
143 | View v = view.itemView;
144 | v.post(() -> {
145 | if (v.getBackground() != null) {
146 | final int centerX = v.getWidth() / 2;
147 | final int centerY = v.getHeight() / 2;
148 | v.getBackground().setHotspot(centerX, centerY);
149 | }
150 | v.setPressed(true);
151 | v.setPressed(false);
152 | mShouldBlink = false;
153 | });
154 | }
155 | mSeekBar.setAccessibilityDelegate(new View.AccessibilityDelegate() {
156 | @Override
157 | public void onInitializeAccessibilityNodeInfo(View view, AccessibilityNodeInfo info) {
158 | super.onInitializeAccessibilityNodeInfo(view, info);
159 | // Update the range info with the correct type
160 | AccessibilityNodeInfo.RangeInfo rangeInfo = info.getRangeInfo();
161 | if (rangeInfo != null) {
162 | info.setRangeInfo(AccessibilityNodeInfo.RangeInfo.obtain(
163 | mAccessibilityRangeInfoType, rangeInfo.getMin(),
164 | rangeInfo.getMax(), rangeInfo.getCurrent()));
165 | }
166 | if (mOverrideSeekBarStateDescription != null) {
167 | info.setStateDescription(mOverrideSeekBarStateDescription);
168 | }
169 | }
170 | });
171 | }
172 |
173 | @Override
174 | public CharSequence getSummary() {
175 | return null;
176 | }
177 |
178 | @Override
179 | protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
180 | setProgress(restoreValue ? getPersistedInt(mProgress)
181 | : (Integer) defaultValue);
182 | }
183 |
184 | @Override
185 | protected Object onGetDefaultValue(TypedArray a, int index) {
186 | return a.getInt(index, 0);
187 | }
188 |
189 | @Override
190 | public boolean onKey(View v, int keyCode, KeyEvent event) {
191 | if (event.getAction() != KeyEvent.ACTION_DOWN) {
192 | return false;
193 | }
194 |
195 | SeekBar seekBar = (SeekBar) v.findViewById(com.android.internal.R.id.seekbar);
196 | if (seekBar == null) {
197 | return false;
198 | }
199 | return seekBar.onKeyDown(keyCode, event);
200 | }
201 |
202 | public void setMax(int max) {
203 | if (max != mMax) {
204 | mMax = max;
205 | notifyChanged();
206 | }
207 | }
208 |
209 | public void setMin(int min) {
210 | if (min != mMin) {
211 | mMin = min;
212 | notifyChanged();
213 | }
214 | }
215 |
216 | public int getMax() {
217 | return mMax;
218 | }
219 |
220 | public int getMin() {
221 | return mMin;
222 | }
223 |
224 | public void setProgress(int progress) {
225 | setProgress(progress, true);
226 | }
227 |
228 | /**
229 | * Sets the progress point to draw a single tick mark representing a default value.
230 | */
231 | public void setDefaultProgress(int defaultProgress) {
232 | if (mDefaultProgress != defaultProgress) {
233 | mDefaultProgress = defaultProgress;
234 | if (mSeekBar instanceof DefaultIndicatorSeekBar) {
235 | ((DefaultIndicatorSeekBar) mSeekBar).setDefaultProgress(mDefaultProgress);
236 | }
237 | }
238 | }
239 |
240 | /**
241 | * When {@code continuousUpdates} is true, update the persisted setting immediately as the thumb
242 | * is dragged along the SeekBar. Otherwise, only update the value of the setting when the thumb
243 | * is dropped.
244 | */
245 | public void setContinuousUpdates(boolean continuousUpdates) {
246 | mContinuousUpdates = continuousUpdates;
247 | }
248 |
249 | /**
250 | * Sets the haptic feedback mode. HAPTIC_FEEDBACK_MODE_ON_TICKS means to perform haptic feedback
251 | * as the SeekBar's progress is updated; HAPTIC_FEEDBACK_MODE_ON_ENDS means to perform haptic
252 | * feedback as the SeekBar's progress value is equal to the min/max value.
253 | *
254 | * @param hapticFeedbackMode the haptic feedback mode.
255 | */
256 | public void setHapticFeedbackMode(int hapticFeedbackMode) {
257 | mHapticFeedbackMode = hapticFeedbackMode;
258 | }
259 |
260 | private void setProgress(int progress, boolean notifyChanged) {
261 | if (progress > mMax) {
262 | progress = mMax;
263 | }
264 | if (progress < mMin) {
265 | progress = mMin;
266 | }
267 | if (progress != mProgress) {
268 | mProgress = progress;
269 | persistInt(progress);
270 | if (notifyChanged) {
271 | notifyChanged();
272 | }
273 | }
274 | }
275 |
276 | public int getProgress() {
277 | return mProgress;
278 | }
279 |
280 | /**
281 | * Persist the seekBar's progress value if callChangeListener
282 | * returns true, otherwise set the seekBar's progress to the stored value
283 | */
284 | void syncProgress(SeekBar seekBar) {
285 | int progress = seekBar.getProgress();
286 | if (progress != mProgress) {
287 | if (callChangeListener(progress)) {
288 | setProgress(progress, false);
289 | switch (mHapticFeedbackMode) {
290 | case HAPTIC_FEEDBACK_MODE_ON_TICKS:
291 | seekBar.performHapticFeedback(CLOCK_TICK);
292 | break;
293 | case HAPTIC_FEEDBACK_MODE_ON_ENDS:
294 | if (progress == mMax || progress == mMin) {
295 | seekBar.performHapticFeedback(CLOCK_TICK);
296 | }
297 | break;
298 | }
299 | } else {
300 | seekBar.setProgress(mProgress);
301 | }
302 | }
303 | }
304 |
305 | @Override
306 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
307 | if (fromUser && (mContinuousUpdates || !mTrackingTouch)) {
308 | syncProgress(seekBar);
309 | }
310 | }
311 |
312 | @Override
313 | public void onStartTrackingTouch(SeekBar seekBar) {
314 | mTrackingTouch = true;
315 | }
316 |
317 | @Override
318 | public void onStopTrackingTouch(SeekBar seekBar) {
319 | mTrackingTouch = false;
320 | if (seekBar.getProgress() != mProgress) {
321 | syncProgress(seekBar);
322 | }
323 | }
324 |
325 | /**
326 | * Specify the type of range this seek bar represents.
327 | *
328 | * @param rangeInfoType The type of range to be shared with accessibility
329 | *
330 | * @see android.view.accessibility.AccessibilityNodeInfo.RangeInfo
331 | */
332 | public void setAccessibilityRangeInfoType(int rangeInfoType) {
333 | mAccessibilityRangeInfoType = rangeInfoType;
334 | }
335 |
336 | public void setSeekBarContentDescription(CharSequence contentDescription) {
337 | mSeekBarContentDescription = contentDescription;
338 | if (mSeekBar != null) {
339 | mSeekBar.setContentDescription(contentDescription);
340 | }
341 | }
342 |
343 | /**
344 | * Specify the state description for this seek bar represents.
345 | *
346 | * @param stateDescription the state description of seek bar
347 | */
348 | public void setSeekBarStateDescription(CharSequence stateDescription) {
349 | mSeekBarStateDescription = stateDescription;
350 | if (mSeekBar != null) {
351 | mSeekBar.setStateDescription(stateDescription);
352 | }
353 | }
354 |
355 | /**
356 | * Overrides the state description of {@link SeekBar} with given content.
357 | */
358 | public void overrideSeekBarStateDescription(CharSequence stateDescription) {
359 | mOverrideSeekBarStateDescription = stateDescription;
360 | }
361 |
362 | @Override
363 | protected Parcelable onSaveInstanceState() {
364 | /*
365 | * Suppose a client uses this preference type without persisting. We
366 | * must save the instance state so it is able to, for example, survive
367 | * orientation changes.
368 | */
369 |
370 | final Parcelable superState = super.onSaveInstanceState();
371 | if (isPersistent()) {
372 | // No need to save instance state since it's persistent
373 | return superState;
374 | }
375 |
376 | // Save the instance state
377 | final SavedState myState = new SavedState(superState);
378 | myState.progress = mProgress;
379 | myState.max = mMax;
380 | myState.min = mMin;
381 | return myState;
382 | }
383 |
384 | @Override
385 | protected void onRestoreInstanceState(Parcelable state) {
386 | if (!state.getClass().equals(SavedState.class)) {
387 | // Didn't save state for us in onSaveInstanceState
388 | super.onRestoreInstanceState(state);
389 | return;
390 | }
391 |
392 | // Restore the instance state
393 | SavedState myState = (SavedState) state;
394 | super.onRestoreInstanceState(myState.getSuperState());
395 | mProgress = myState.progress;
396 | mMax = myState.max;
397 | mMin = myState.min;
398 | notifyChanged();
399 | }
400 |
401 | /**
402 | * SavedState, a subclass of {@link BaseSavedState}, will store the state
403 | * of MyPreference, a subclass of Preference.
404 | *
405 | * It is important to always call through to super methods.
406 | */
407 | private static class SavedState extends BaseSavedState {
408 | int progress;
409 | int max;
410 | int min;
411 |
412 | public SavedState(Parcel source) {
413 | super(source);
414 |
415 | // Restore the click counter
416 | progress = source.readInt();
417 | max = source.readInt();
418 | min = source.readInt();
419 | }
420 |
421 | @Override
422 | public void writeToParcel(Parcel dest, int flags) {
423 | super.writeToParcel(dest, flags);
424 |
425 | // Save the click counter
426 | dest.writeInt(progress);
427 | dest.writeInt(max);
428 | dest.writeInt(min);
429 | }
430 |
431 | public SavedState(Parcelable superState) {
432 | super(superState);
433 | }
434 |
435 | @SuppressWarnings("unused")
436 | public static final Parcelable.Creator CREATOR =
437 | new Parcelable.Creator() {
438 | public SavedState createFromParcel(Parcel in) {
439 | return new SavedState(in);
440 | }
441 |
442 | public SavedState[] newArray(int size) {
443 | return new SavedState[size];
444 | }
445 | };
446 | }
447 | }
448 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/BootReceiver.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra
18 |
19 | import android.content.BroadcastReceiver
20 | import android.content.Context
21 | import android.content.Intent
22 |
23 | class BootReceiver : BroadcastReceiver() {
24 | override fun onReceive(context: Context?, intent: Intent?) {
25 | Intent(context ?: return, ElmyraService::class.java).also {
26 | context.startService(it)
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/Constants.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra
18 |
19 | const val TAG = "Elmyra/Service"
20 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/ElmyraService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra
18 |
19 | import android.app.Service
20 | import android.content.BroadcastReceiver
21 | import android.content.Context
22 | import android.content.Intent
23 | import android.content.SharedPreferences
24 | import android.content.IntentFilter
25 | import android.hardware.location.ContextHubClient
26 | import android.hardware.location.ContextHubClientCallback
27 | import android.hardware.location.ContextHubManager
28 | import android.hardware.location.NanoAppMessage
29 | import android.os.SystemClock
30 | import android.os.VibrationEffect
31 | import android.os.Vibrator
32 | import android.util.Log
33 | import androidx.preference.PreferenceManager
34 |
35 | import com.google.protobuf.nano.MessageNano
36 |
37 | import org.protonaosp.elmyra.actions.*
38 | import org.protonaosp.elmyra.proto.nano.ContextHubMessages
39 | import org.protonaosp.elmyra.TAG
40 | import org.protonaosp.elmyra.getDePrefs
41 | import org.protonaosp.elmyra.getAction
42 | import org.protonaosp.elmyra.getSensitivity
43 | import org.protonaosp.elmyra.getEnabled
44 | import org.protonaosp.elmyra.getAllowScreenOff
45 |
46 | private const val NANOAPP_ID = 0x476f6f676c00100eL
47 | private const val REJECT_COOLDOWN_TIME = 1000 // ms
48 |
49 | class ElmyraService : Service(), SharedPreferences.OnSharedPreferenceChangeListener {
50 | // Services
51 | private lateinit var vibrator: Vibrator
52 | private lateinit var prefs: SharedPreferences
53 | private lateinit var action: Action
54 | private lateinit var client: ContextHubClient
55 |
56 | // State
57 | private var inGesture = false
58 | private var screenRegistered = false
59 | private var lastRejectTime = 0L - REJECT_COOLDOWN_TIME
60 |
61 | // Settings
62 | private var enabled = true
63 | private var sensitivity = 0.5f
64 | set(value) {
65 | field = value
66 | if (enabled) {
67 | sendNewSensitivity()
68 | }
69 | }
70 |
71 | override fun onBind(intent: Intent?) = null
72 |
73 | override fun onCreate() {
74 | vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
75 | prefs = getDePrefs()
76 |
77 | Log.i(TAG, "Initializing CHRE gesture")
78 |
79 | val manager = getSystemService("contexthub") as ContextHubManager
80 | client = manager.createClient(manager.contextHubs[0], chreCallback)
81 |
82 | updateAction()
83 | updateSensitivity()
84 | updateEnabled()
85 | updateScreenCallback()
86 |
87 | // Only register for changes after initial pref updates
88 | prefs.registerOnSharedPreferenceChangeListener(this)
89 | }
90 |
91 | override fun onDestroy() {
92 | prefs.unregisterOnSharedPreferenceChangeListener(this)
93 | unregisterReceiver(screenCallback)
94 | }
95 |
96 | private fun createAction(key: String): Action {
97 | return when (key) {
98 | "screenshot" -> ScreenshotAction(this)
99 | "assistant" -> AssistantAction(this)
100 | "camera" -> CameraAction(this)
101 | "power_menu" -> PowerMenuAction(this)
102 | "mute" -> MuteAction(this)
103 | "flashlight" -> FlashlightAction(this)
104 | "screen" -> ScreenAction(this)
105 |
106 | else -> DummyAction(this)
107 | }
108 | }
109 |
110 | private fun updateSensitivity() {
111 | sensitivity = prefs.getSensitivity(this) / 10f
112 | Log.i(TAG, "Setting sensitivity to $sensitivity")
113 | }
114 |
115 | private fun updateAction() {
116 | val key = prefs.getAction(this)
117 | Log.i(TAG, "Setting action to $key")
118 | action = createAction(key)
119 |
120 | // For settings
121 | prefs.edit().putBoolean(getString(R.string.pref_key_allow_screen_off_action_forced),
122 | !action.canRunWhenScreenOff()).commit()
123 | }
124 |
125 | private fun updateEnabled() {
126 | enabled = prefs.getEnabled(this)
127 | if (enabled) {
128 | Log.i(TAG, "Enabling gesture by pref")
129 | enableGesture()
130 | } else {
131 | Log.i(TAG, "Disabling gesture by pref")
132 | disableGesture()
133 | }
134 | }
135 |
136 | private fun updateScreenCallback() {
137 | val allowScreenOff = prefs.getAllowScreenOff(this)
138 |
139 | // Listen if either condition *can't* run when screen is off
140 | if (!allowScreenOff || !action.canRunWhenScreenOff()) {
141 | val filter = IntentFilter().apply {
142 | addAction(Intent.ACTION_SCREEN_ON)
143 | addAction(Intent.ACTION_SCREEN_OFF)
144 | }
145 |
146 | if (!screenRegistered) {
147 | Log.i(TAG, "Listening to screen on/off events")
148 | registerReceiver(screenCallback, filter)
149 | screenRegistered = true
150 | }
151 | } else if (screenRegistered) {
152 | Log.i(TAG, "Stopped listening to screen on/off events")
153 | unregisterReceiver(screenCallback)
154 | screenRegistered = false
155 | }
156 | }
157 |
158 | override fun onSharedPreferenceChanged(prefs: SharedPreferences, key: String) {
159 | when (key) {
160 | getString(R.string.pref_key_enabled) -> updateEnabled()
161 | getString(R.string.pref_key_sensitivity) -> updateSensitivity()
162 | // Action might change screen callback behavior
163 | getString(R.string.pref_key_action) -> {
164 | updateAction()
165 | updateScreenCallback()
166 | }
167 | getString(R.string.pref_key_allow_screen_off) -> updateScreenCallback()
168 | }
169 | }
170 |
171 | private fun enableGesture() {
172 | val msg = ContextHubMessages.RecognizerStart()
173 | // Only report events to AP if gesture is halfway done
174 | msg.progressReportThreshold = 0.5f
175 | msg.sensitivity = sensitivity
176 |
177 | sendNanoappMsg(MessageType.RECOGNIZER_START.id, MessageNano.toByteArray(msg))
178 | }
179 |
180 | private fun disableGesture() {
181 | sendNanoappMsg(MessageType.RECOGNIZER_STOP.id, ByteArray(0))
182 | }
183 |
184 | private fun sendNewSensitivity() {
185 | val msg = ContextHubMessages.SensitivityUpdate()
186 | msg.sensitivity = sensitivity
187 | sendNanoappMsg(MessageType.SENSITIVITY_UPDATE.id, MessageNano.toByteArray(msg))
188 | }
189 |
190 | private fun sendNanoappMsg(msgType: Int, bytes: ByteArray) {
191 | val message = NanoAppMessage.createMessageToNanoApp(NANOAPP_ID, msgType, bytes)
192 | val ret = client.sendMessageToNanoApp(message)
193 | if (ret != 0) {
194 | Log.e(TAG, "Failed to send message of type $msgType to nanoapp: $ret")
195 | }
196 | }
197 |
198 | private fun onGestureDetected(msg: ContextHubMessages.GestureDetected) {
199 | Log.i(TAG, "Gesture detected hostSuspended=${msg.hostSuspended} hapticConsumed=${msg.hapticConsumed}")
200 |
201 | if (action.canRun()) {
202 | if (!msg.hapticConsumed) {
203 | vibrator.vibrate(vibEdgeRelease)
204 | }
205 |
206 | action.run()
207 | inGesture = false
208 | }
209 | }
210 |
211 | private fun onGestureProgress(msg: ContextHubMessages.GestureProgress) {
212 | // Ignore beginning and end points
213 | if (msg.progress < 0.49f || msg.progress > 0.99f) {
214 | inGesture = false
215 | } else if (!inGesture) {
216 | if (action.canRun()) {
217 | // Enter gesture and vibrate to indicate that
218 | inGesture = true
219 | vibrator.vibrate(vibEdgeSqueeze)
220 | } else {
221 | val now = SystemClock.elapsedRealtime()
222 | if (now - lastRejectTime >= REJECT_COOLDOWN_TIME) {
223 | vibrator.vibrate(vibReject)
224 | lastRejectTime = now
225 | }
226 | }
227 | }
228 | }
229 |
230 | private val chreCallback = object : ContextHubClientCallback() {
231 | override fun onMessageFromNanoApp(client: ContextHubClient, msg: NanoAppMessage) {
232 | // Ignore other nanoapps
233 | if (msg.nanoAppId != NANOAPP_ID) {
234 | return
235 | }
236 |
237 | when (msg.messageType) {
238 | MessageType.GESTURE_DETECTED.id -> {
239 | val detectedMsg = ContextHubMessages.GestureDetected.parseFrom(msg.messageBody)
240 | onGestureDetected(detectedMsg)
241 | }
242 | MessageType.GESTURE_PROGRESS.id -> {
243 | val progressMsg = ContextHubMessages.GestureProgress.parseFrom(msg.messageBody)
244 | onGestureProgress(progressMsg)
245 | }
246 |
247 | // Fallback for other unexpected messages
248 | else -> Log.w(TAG, "Received unknown message of type ${msg.messageType}: $msg")
249 | }
250 | }
251 |
252 | override fun onNanoAppAborted(client: ContextHubClient, nanoappId: Long, error: Int) {
253 | if (nanoappId == NANOAPP_ID) {
254 | Log.e(TAG, "Elmyra CHRE nanoapp aborted: $error")
255 | }
256 | }
257 | }
258 |
259 | private val screenCallback = object : BroadcastReceiver() {
260 | override fun onReceive(context: Context?, intent: Intent?) {
261 | if (enabled) {
262 | when (intent?.action) {
263 | Intent.ACTION_SCREEN_ON -> {
264 | Log.i(TAG, "Enabling gesture due to screen on")
265 | enableGesture()
266 | }
267 | // Disable gesture entirely to save power
268 | Intent.ACTION_SCREEN_OFF -> {
269 | Log.i(TAG, "Disabling gesture due to screen off")
270 | disableGesture()
271 | }
272 | }
273 | }
274 | }
275 | }
276 |
277 | companion object {
278 | // Vibration effects from HapticFeedbackConstants
279 | // Duplicated because we can't use performHapticFeedback in a background service
280 | private val vibEdgeRelease = VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)
281 | private val vibEdgeSqueeze = VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK)
282 | private val vibReject = VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK)
283 | }
284 | }
285 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/MessageType.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra
18 |
19 | enum class MessageType(val id: Int) {
20 | RECOGNIZER_START(200),
21 | RECOGNIZER_STOP(201),
22 | SENSITIVITY_UPDATE(202),
23 | SNAPSHOT_REQUEST(203),
24 | CHASSIS_REQUEST(204),
25 | GRAB_RECOGNIZER_START(205),
26 | GRAB_RECOGNIZER_STOP(206),
27 | GESTURE_PROGRESS(300),
28 | GESTURE_DETECTED(301),
29 | SNAPSHOT_RESPONSE(302),
30 | CHASSIS_RESPONSE(303),
31 | GRAB_DETECTED(304),
32 | GRAB_RELEASED(305),
33 | }
34 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/Preferences.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra
18 |
19 | import android.content.Context
20 | import android.content.SharedPreferences
21 |
22 | const val PREFS_NAME = "elmyra_preferences"
23 |
24 | fun Context.getDePrefs(): SharedPreferences {
25 | return createDeviceProtectedStorageContext()
26 | .getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
27 | }
28 |
29 | fun SharedPreferences.getEnabled(context: Context): Boolean {
30 | return getBoolean(context.getString(R.string.pref_key_enabled),
31 | context.resources.getBoolean(R.bool.default_enabled))
32 | }
33 |
34 | fun SharedPreferences.getAction(context: Context): String {
35 | return getString(context.getString(R.string.pref_key_action),
36 | context.getString(R.string.default_action))
37 | }
38 |
39 | fun SharedPreferences.getAllowScreenOff(context: Context): Boolean {
40 | return getBoolean(context.getString(R.string.pref_key_allow_screen_off),
41 | context.resources.getBoolean(R.bool.default_allow_screen_off))
42 | }
43 |
44 | fun SharedPreferences.getSensitivity(context: Context): Int {
45 | return getInt(context.getString(R.string.pref_key_sensitivity),
46 | context.resources.getInteger(R.integer.default_sensitivity))
47 | }
48 |
49 | fun SharedPreferences.getActionName(context: Context): String {
50 | val actionNames = context.resources.getStringArray(R.array.action_names)
51 | val actionValues = context.resources.getStringArray(R.array.action_values)
52 | return actionNames[actionValues.indexOf(getAction(context))]
53 | }
54 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/actions/Action.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.actions
18 |
19 | import android.content.Context
20 |
21 | abstract class Action(val context: Context) {
22 | open fun canRun() = true
23 | open fun canRunWhenScreenOff() = true
24 | abstract fun run()
25 |
26 | open fun destroy() {}
27 | }
28 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/actions/AssistantAction.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.actions
18 |
19 | import android.app.StatusBarManager
20 | import android.content.Context
21 | import android.os.Bundle
22 | import android.os.ServiceManager
23 |
24 | import com.android.internal.statusbar.IStatusBarService
25 |
26 | class AssistantAction(context: Context) : Action(context) {
27 | val service = IStatusBarService.Stub.asInterface(ServiceManager.getService(Context.STATUS_BAR_SERVICE))
28 |
29 | override fun run() {
30 | service.startAssist(Bundle())
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/actions/CameraAction.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.actions
18 |
19 | import android.app.StatusBarManager
20 | import android.content.Context
21 | import android.content.Intent
22 | import android.os.PowerManager
23 | import android.os.SystemClock
24 | import android.provider.MediaStore
25 |
26 | class CameraAction(context: Context) : Action(context) {
27 | val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
28 |
29 | override fun run() {
30 | if (!pm.isInteractive()) {
31 | pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
32 | "org.protonaosp.elmyra:GESTURE")
33 | }
34 |
35 | val intent = Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE).apply {
36 | addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS or
37 | Intent.FLAG_ACTIVITY_NEW_TASK)
38 | }
39 | context.startActivity(intent)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/actions/DummyAction.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.actions
18 |
19 | import android.content.Context
20 |
21 | class DummyAction(context: Context) : Action(context) {
22 | override fun run() {}
23 | }
24 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/actions/FlashlightAction.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.actions
18 |
19 | import android.content.Context
20 | import android.os.Handler
21 | import android.os.Looper
22 | import android.hardware.camera2.CameraAccessException
23 | import android.hardware.camera2.CameraCharacteristics
24 | import android.hardware.camera2.CameraManager
25 | import android.util.Log
26 |
27 | import org.protonaosp.elmyra.TAG
28 |
29 | class FlashlightAction(context: Context) : Action(context) {
30 | private val handler = Handler(Looper.getMainLooper())
31 | private val cm = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
32 | private val torchCamId = findCamera()
33 | private var available = true
34 | private var enabled = false
35 |
36 | private val torchCallback = object : CameraManager.TorchCallback() {
37 | override fun onTorchModeUnavailable(cameraId: String) {
38 | if (cameraId == torchCamId) {
39 | available = false
40 | }
41 | }
42 |
43 | override fun onTorchModeChanged(cameraId: String, newEnabled: Boolean) {
44 | if (cameraId == torchCamId) {
45 | available = true
46 | enabled = newEnabled
47 | }
48 | }
49 | }
50 |
51 | init {
52 | if (torchCamId != null) {
53 | cm.registerTorchCallback(torchCallback, handler)
54 | }
55 | }
56 |
57 | override fun canRun() = torchCamId != null && available
58 |
59 | override fun run() {
60 | try {
61 | cm.setTorchMode(torchCamId, !enabled)
62 | } catch (e: CameraAccessException) {
63 | Log.e(TAG, "Failed to set torch mode to $enabled", e)
64 | return
65 | }
66 |
67 | enabled = !enabled
68 | }
69 |
70 | override fun destroy() {
71 | if (torchCamId != null) {
72 | cm.unregisterTorchCallback(torchCallback)
73 | }
74 | }
75 |
76 | private fun findCamera(): String? {
77 | for (id in cm.cameraIdList) {
78 | val characteristics = cm.getCameraCharacteristics(id)
79 | val flashAvailable = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE)
80 | val lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING)
81 |
82 | if (flashAvailable != null && flashAvailable && lensFacing != null &&
83 | lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
84 | return id
85 | }
86 | }
87 |
88 | return null
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/actions/MuteAction.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.actions
18 |
19 | import android.content.Context
20 | import android.media.AudioManager
21 | import android.os.UserHandle
22 | import android.provider.Settings
23 | import android.widget.Toast
24 |
25 | class MuteAction(context: Context) : Action(context) {
26 | val service = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
27 |
28 | override fun canRun() = context.resources.getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)
29 |
30 | override fun run() {
31 | // We can't call AudioService#silenceRingerModeInternal from here, so this is a partial copy of it
32 | var silenceRingerSetting = Settings.Secure.getIntForUser(context.contentResolver,
33 | Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_OFF,
34 | UserHandle.USER_CURRENT)
35 |
36 | var ringerMode: Int
37 | var toastText: Int
38 | when (silenceRingerSetting) {
39 | Settings.Secure.VOLUME_HUSH_VIBRATE -> {
40 | ringerMode = AudioManager.RINGER_MODE_VIBRATE
41 | toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate
42 | }
43 | // VOLUME_HUSH_MUTE and VOLUME_HUSH_OFF
44 | else -> {
45 | ringerMode = AudioManager.RINGER_MODE_SILENT
46 | toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent
47 | }
48 | }
49 |
50 | service.setRingerModeInternal(ringerMode)
51 | Toast.makeText(context, toastText, Toast.LENGTH_SHORT).show()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/actions/PowerMenuAction.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.actions
18 |
19 | import android.content.Context
20 | import android.os.PowerManager
21 | import android.os.SystemClock
22 | import android.view.IWindowManager
23 | import android.view.WindowManagerGlobal
24 |
25 | class PowerMenuAction(context: Context) : Action(context) {
26 | val wm = WindowManagerGlobal.getWindowManagerService()
27 | val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
28 |
29 | override fun run() {
30 | if (!pm.isInteractive()) {
31 | pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, "org.protonaosp.elmyra:GESTURE")
32 | }
33 |
34 | wm.showGlobalActions()
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/actions/ScreenAction.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.actions
18 |
19 | import android.content.Context
20 | import android.os.PowerManager
21 | import android.os.SystemClock
22 |
23 | class ScreenAction(context: Context) : Action(context) {
24 | val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
25 |
26 | override fun run() {
27 | if (pm.isInteractive()) {
28 | pm.goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0)
29 | } else {
30 | pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, "org.protonaosp.elmyra:GESTURE")
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/actions/ScreenshotAction.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.actions
18 |
19 | import android.content.Context
20 | import android.os.Handler
21 | import android.os.Looper
22 | import android.os.PowerManager
23 | import android.view.WindowManager
24 |
25 | import com.android.internal.util.ScreenshotHelper
26 |
27 | class ScreenshotAction(context: Context) : Action(context) {
28 | val helper = ScreenshotHelper(context)
29 | private val handler = Handler(Looper.getMainLooper())
30 | val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
31 |
32 | override fun canRun() = pm.isInteractive()
33 | override fun canRunWhenScreenOff() = false
34 |
35 | override fun run() {
36 | helper.takeScreenshot(WindowManager.TAKE_SCREENSHOT_FULLSCREEN,
37 | true, true, WindowManager.ScreenshotSource.SCREENSHOT_OTHER,
38 | handler, null)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/proto/chre_messages.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package org.protonaosp.elmyra.proto;
4 |
5 | option java_outer_classname = "ContextHubMessages";
6 | option java_package = "org.protonaosp.elmyra.proto";
7 |
8 | message RecognizerStart {
9 | // Minimum gesture progress threshold for reporting events to AP
10 | float progress_report_threshold = 1;
11 | // Gesture trigger sensitivty (1.0 scale)
12 | float sensitivity = 2;
13 | }
14 |
15 | message SensitivityUpdate {
16 | // Gesture trigger sensitivty (1.0 scale)
17 | float sensitivity = 1;
18 | }
19 |
20 | message GestureProgress {
21 | // Progress towards finished gesture (GestureDetected event), 0.0-1.0
22 | float progress = 1;
23 | }
24 |
25 | message GestureDetected {
26 | // Was AP suspended when the gesture was finished?
27 | // If so, we didn't get any progress events for this gesture
28 | bool host_suspended = 1;
29 | // Did SLPI perform the vibration or does the AP need to do it?
30 | bool haptic_consumed = 2;
31 | }
32 |
33 | enum MessageType {
34 | // Dummy value to make protobuf happy
35 | UNDEFINED = 0;
36 |
37 | /*
38 | * From AP HALs
39 | */
40 |
41 | NANOAPP_LOADED = 1;
42 | // napp_header values loaded?
43 | NANOAPP_CONFIG = 100;
44 |
45 | /*
46 | * AP -> SLPI
47 | */
48 |
49 | // Enable gesture with specified sensitivity
50 | RECOGNIZER_START = 200;
51 | // Disable gesture
52 | RECOGNIZER_STOP = 201;
53 | // Set new sensitivity without restarting gesture
54 | SENSITIVITY_UPDATE = 202;
55 | // For debugging: replies with recent raw sensor data
56 | SNAPSHOT_REQUEST = 203;
57 | // For debugging: replies with sensor chassis calibration
58 | CHASSIS_REQUEST = 204;
59 | // Abandoned grab gesture?
60 | GRAB_RECOGNIZER_START = 205;
61 | // Abandoned grab gesture?
62 | GRAB_RECOGNIZER_STOP = 206;
63 |
64 | /*
65 | * SLPI -> AP
66 | */
67 |
68 | // Squeeze is in progress and above report threshold sent in RECOGNIZER_START
69 | GESTURE_PROGRESS = 300;
70 | // Squeeze released (SLPI may or may not have vibrated)
71 | GESTURE_DETECTED = 301;
72 | // Recent raw sensor data for debugging
73 | SNAPSHOT_RESPONSE = 302;
74 | // Sensor calibration values for device chassis
75 | CHASSIS_RESPONSE = 303;
76 | // Corresponds to GRAB_RECOGNIZER_START
77 | GRAB_DETECTED = 304;
78 | // Corresponds to GRAB_RECOGNIZER_STOP
79 | GRAB_RELEASED = 305;
80 | }
81 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/settings/SearchProvider.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.settings
18 |
19 | import android.content.Intent
20 | import android.database.Cursor
21 | import android.database.MatrixCursor
22 | import android.provider.SearchIndexablesProvider
23 | import android.provider.SearchIndexablesContract.*
24 |
25 | import org.protonaosp.elmyra.R
26 |
27 | class SearchProvider : SearchIndexablesProvider() {
28 | override fun onCreate() = true
29 | override fun queryXmlResources(projection: Array?) = MatrixCursor(INDEXABLES_XML_RES_COLUMNS)
30 | override fun queryNonIndexableKeys(projection: Array?) = MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS)
31 |
32 | override fun queryRawData(projection: Array?): Cursor {
33 | val ref = Array(INDEXABLES_RAW_COLUMNS.size) { null }
34 | ref[COLUMN_INDEX_RAW_KEY] = context.getString(R.string.settings_entry_title)
35 | ref[COLUMN_INDEX_RAW_TITLE] = context.getString(R.string.settings_entry_title)
36 | ref[COLUMN_INDEX_RAW_SUMMARY_ON] = context.getString(R.string.setting_enabled_summary)
37 | ref[COLUMN_INDEX_RAW_KEYWORDS] = context.getString(R.string.settings_search_keywords)
38 |
39 | // For breadcrumb generation
40 | ref[COLUMN_INDEX_RAW_SCREEN_TITLE] = context.getString(R.string.settings_entry_title)
41 | ref[COLUMN_INDEX_RAW_CLASS_NAME] = SettingsActivity::class.java.name
42 |
43 | ref[COLUMN_INDEX_RAW_INTENT_ACTION] = Intent.ACTION_MAIN
44 | ref[COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE] = context.applicationInfo.packageName
45 | ref[COLUMN_INDEX_RAW_INTENT_TARGET_CLASS] = SettingsActivity::class.java.name
46 |
47 | return MatrixCursor(INDEXABLES_RAW_COLUMNS).apply {
48 | addRow(ref)
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/settings/SettingsActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.settings
18 |
19 | import android.os.Bundle
20 |
21 | import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity
22 |
23 | import org.protonaosp.elmyra.R
24 |
25 | class SettingsActivity : CollapsingToolbarBaseActivity() {
26 | override fun onCreate(savedInstanceState: Bundle?) {
27 | super.onCreate(savedInstanceState)
28 | setContentView(R.layout.settings_activity)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/settings/SettingsFragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.settings
18 |
19 | import android.os.Bundle
20 | import android.content.SharedPreferences
21 | import androidx.preference.PreferenceFragmentCompat
22 | import androidx.preference.PreferenceManager
23 | import androidx.preference.ListPreference
24 | import androidx.preference.SwitchPreference
25 | import com.android.settings.widget.LabeledSeekBarPreference
26 | import com.android.settings.widget.SeekBarPreference
27 |
28 | import org.protonaosp.elmyra.R
29 | import org.protonaosp.elmyra.getDePrefs
30 | import org.protonaosp.elmyra.PREFS_NAME
31 | import org.protonaosp.elmyra.getEnabled
32 | import org.protonaosp.elmyra.getSensitivity
33 | import org.protonaosp.elmyra.getAction
34 | import org.protonaosp.elmyra.getActionName
35 | import org.protonaosp.elmyra.getAllowScreenOff
36 |
37 | class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener {
38 | private lateinit var prefs: SharedPreferences
39 |
40 | override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
41 | setPreferencesFromResource(R.xml.settings, rootKey)
42 | }
43 |
44 | override fun onCreate(savedInstanceState: Bundle?) {
45 | super.onCreate(savedInstanceState)
46 | preferenceManager.setStorageDeviceProtected()
47 | preferenceManager.sharedPreferencesName = PREFS_NAME
48 |
49 | prefs = context!!.getDePrefs()
50 | prefs.registerOnSharedPreferenceChangeListener(this)
51 | updateUi()
52 | }
53 |
54 | override fun onDestroy() {
55 | super.onDestroy()
56 | prefs.unregisterOnSharedPreferenceChangeListener(this)
57 | }
58 |
59 | override fun onSharedPreferenceChanged(prefs: SharedPreferences, key: String) {
60 | updateUi()
61 | }
62 |
63 | private fun updateUi() {
64 | // Enabled
65 | findPreference(getString(R.string.pref_key_enabled))?.apply {
66 | setChecked(prefs.getEnabled(context))
67 | }
68 |
69 | // Sensitivity value
70 | findPreference(getString(R.string.pref_key_sensitivity))?.apply {
71 | progress = prefs.getSensitivity(context)
72 | setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_TICKS)
73 | }
74 |
75 | // Action value and summary
76 | findPreference(getString(R.string.pref_key_action))?.apply {
77 | value = prefs.getAction(context)
78 | summary = prefs.getActionName(context)
79 | }
80 |
81 | // Screen state based on action
82 | findPreference(getString(R.string.pref_key_allow_screen_off))?.apply {
83 | val screenForced = prefs.getBoolean(getString(R.string.pref_key_allow_screen_off_action_forced), false)
84 | setEnabled(!screenForced)
85 | if (screenForced) {
86 | setSummary(getString(R.string.setting_screen_off_blocked_summary))
87 | setPersistent(false)
88 | setChecked(false)
89 | } else {
90 | setSummary(getString(R.string.setting_screen_off_summary))
91 | setPersistent(true)
92 | setChecked(prefs.getAllowScreenOff(context))
93 | }
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/settings/SummaryProvider.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.settings
18 |
19 | import android.content.ContentProvider
20 | import android.content.ContentValues
21 | import android.content.SharedPreferences
22 | import android.database.Cursor
23 | import android.net.Uri
24 | import android.os.Bundle
25 | import com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY
26 |
27 | import org.protonaosp.elmyra.R
28 | import org.protonaosp.elmyra.getDePrefs
29 | import org.protonaosp.elmyra.getEnabled
30 | import org.protonaosp.elmyra.getActionName
31 |
32 | class SummaryProvider : ContentProvider() {
33 | private lateinit var prefs: SharedPreferences
34 |
35 | override fun onCreate(): Boolean {
36 | prefs = context.getDePrefs()
37 | return true
38 | }
39 |
40 | override fun call(method: String, uri: String, extras: Bundle?): Bundle {
41 | val bundle = Bundle()
42 | val summary = when (method) {
43 | "entry" -> if (prefs.getEnabled(context)) {
44 | context.getString(R.string.settings_entry_summary_on, prefs.getActionName(context))
45 | } else {
46 | context.getString(R.string.settings_entry_summary_off)
47 | }
48 | else -> throw IllegalArgumentException("Unknown method: $method")
49 | }
50 |
51 | bundle.putString(META_DATA_PREFERENCE_SUMMARY, summary)
52 | return bundle
53 | }
54 |
55 | override fun query(uri: Uri, projection: Array, selection: String,
56 | selectionArgs: Array, sortOrder: String): Cursor {
57 | throw UnsupportedOperationException()
58 | }
59 |
60 | override fun getType(uri: Uri): String {
61 | throw UnsupportedOperationException()
62 | }
63 |
64 | override fun insert(uri: Uri, values: ContentValues): Uri {
65 | throw UnsupportedOperationException()
66 | }
67 |
68 | override fun delete(uri: Uri, selection: String, selectionArgs: Array): Int {
69 | throw UnsupportedOperationException()
70 | }
71 |
72 | override fun update(uri: Uri, values: ContentValues, selection: String, selectionArgs: Array): Int {
73 | throw UnsupportedOperationException()
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/org/protonaosp/elmyra/settings/ToggleTileService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Proton AOSP Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package org.protonaosp.elmyra.settings
18 |
19 | import android.content.Context
20 | import android.content.SharedPreferences
21 | import android.service.quicksettings.Tile
22 | import android.service.quicksettings.TileService
23 | import androidx.preference.PreferenceManager
24 |
25 | import org.protonaosp.elmyra.R
26 | import org.protonaosp.elmyra.getDePrefs
27 | import org.protonaosp.elmyra.getEnabled
28 |
29 | class ToggleTileService : TileService(), SharedPreferences.OnSharedPreferenceChangeListener {
30 | private lateinit var prefs: SharedPreferences
31 |
32 | override fun onStartListening() {
33 | prefs = getDePrefs()
34 | prefs.registerOnSharedPreferenceChangeListener(this)
35 | update()
36 | }
37 |
38 | override fun onStopListening() {
39 | prefs.unregisterOnSharedPreferenceChangeListener(this)
40 | }
41 |
42 | private fun update(state: Boolean? = null) {
43 | qsTile.state = if (state ?: prefs.getEnabled(this)) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
44 | qsTile.updateTile()
45 | }
46 |
47 | override fun onClick() {
48 | val newState = !prefs.getEnabled(this)
49 | prefs.edit().putBoolean(getString(R.string.pref_key_enabled), newState).commit()
50 | update(newState)
51 | }
52 |
53 | override fun onSharedPreferenceChanged(prefs: SharedPreferences, key: String) {
54 | if (key == getString(R.string.pref_key_enabled)) {
55 | update()
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------