diff --git a/res/color/dream_card_color_state_list.xml b/res/color/dream_card_color_state_list.xml index b0c86bba121..0799dc6fab0 100644 --- a/res/color/dream_card_color_state_list.xml +++ b/res/color/dream_card_color_state_list.xml @@ -17,6 +17,8 @@ + \ No newline at end of file diff --git a/res/color/dream_card_text_color_state_list.xml b/res/color/dream_card_text_color_state_list.xml index 438855fd233..2ca7a0fc915 100644 --- a/res/color/dream_card_text_color_state_list.xml +++ b/res/color/dream_card_text_color_state_list.xml @@ -17,6 +17,8 @@ + \ No newline at end of file diff --git a/res/layout/accessibility_text_reading_preview_mail_content.xml b/res/layout/accessibility_text_reading_preview_mail_content.xml index 7b50ac10e93..a8d4e52bdf2 100644 --- a/res/layout/accessibility_text_reading_preview_mail_content.xml +++ b/res/layout/accessibility_text_reading_preview_mail_content.xml @@ -25,6 +25,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/accessibility_text_reading_preview_mail_subject" + android:textSize="14sp" android:textAppearance="?android:attr/textAppearanceMedium" /> @@ -40,6 +42,7 @@ android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" + android:textSize="13sp" android:text="@string/accessibility_text_reading_preview_mail_content" android:textAppearance="?android:attr/textAppearanceMedium" /> diff --git a/res/raw/lottie_button_nav_menu.json b/res/raw/lottie_button_nav_menu.json new file mode 100644 index 00000000000..9581e467b54 --- /dev/null +++ b/res/raw/lottie_button_nav_menu.json @@ -0,0 +1 @@ +{"v":"5.7.6","fr":60,"ip":0,"op":300,"w":412,"h":300,"nm":"Home Button - Digital Assistant V01","ddd":0,"assets":[{"id":"image_0","w":803,"h":479,"u":"","p":"data:image/png;base64,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","e":1}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Gesture Tap","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,264.812,0],"ix":2,"l":2},"a":{"a":0,"k":[273.205,92.869,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-5.226],[-5.226,0],[0,5.226],[5.226,0]],"o":[[0,5.226],[5.226,0],[0,-5.226],[-5.226,0]],"v":[[-9.463,0],[0,9.463],[9.463,0],[0,-9.463]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[273.205,92.869],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.239,0.239],"y":[0.677,0.677]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":40,"s":[0,0]},{"i":{"x":[0.596,0.596],"y":[1,1]},"o":{"x":[0.182,0.182],"y":[0.207,0.207]},"t":55,"s":[80,80]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.793,0.793],"y":[0,0]},"t":75,"s":[120,120]},{"t":85,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":40,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-8.26],[-8.26,0],[0,8.26],[8.26,0]],"o":[[0,8.26],[8.26,0],[0,-8.26],[-8.26,0]],"v":[[-14.957,0],[0,14.957],[14.957,0],[0,-14.957]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[273.205,92.869],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.304,0.304],"y":[0.802,0.802]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":30,"s":[0,0]},{"i":{"x":[0.709,0.709],"y":[0.997,0.997]},"o":{"x":[0.196,0.196],"y":[0.446,0.446]},"t":45,"s":[80,80]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.609,0.609],"y":[0,0]},"t":75,"s":[100,100]},{"t":85,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":40,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Home Button","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":206.025,"ix":3},"y":{"a":0,"k":264.925,"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[34.95,34.95,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.6,0.6],"y":[0,0]},"t":80,"s":[16,16]},{"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0.6,0.6],"y":[0,0]},"t":90,"s":[12,12]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":95,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.4,0.4],"y":[0,0]},"t":107,"s":[0,0]},{"t":116,"s":[16,16]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.563568115234,0.598419189453,0.6806640625,1],"ix":4,"x":"var $bm_rt;\nvar rayColorPalette, rayColorSwatch;\ntry {\n rayColorPalette = 'Ray - palette 01';\n rayColorSwatch = Math.floor($bm_mul(value[2], 255));\n $bm_rt = comp(rayColorPalette).layer(1)(4)(rayColorSwatch)(1);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":516,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Blue_Dot","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":80,"s":[206.025]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[200.782]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":102,"s":[190.298]},{"t":111,"s":[206.025]}],"ix":3},"y":{"a":0,"k":264.925,"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[34.95,34.95,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.4,0.4],"y":[0,0]},"t":80,"s":[10,10]},{"t":93,"s":[8,8]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.101960785687,0.450980395079,0.909803926945,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":118,"st":10,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Yellow_Dot","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[206.025]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":102,"s":[211.267]},{"t":110,"s":[206.025]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":80,"s":[264.925]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[270.168]},{"t":98,"s":[264.925]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[34.95,34.95,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.4,0.4],"y":[0,0]},"t":80,"s":[10,10]},{"t":93,"s":[8,8]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.976470589638,0.670588254929,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":112,"st":10,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Red_Dot","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[206.025]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":102,"s":[200.782]},{"t":110,"s":[206.025]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":80,"s":[264.925]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[259.683]},{"t":98,"s":[264.925]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[34.95,34.95,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.4,0.4],"y":[0,0]},"t":80,"s":[10,10]},{"t":93,"s":[8,8]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.850980401039,0.188235297799,0.145098045468,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":111,"st":10,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Green_Dot","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":80,"s":[206.025]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[211.267]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":102,"s":[221.752]},{"t":111,"s":[206.025]}],"ix":3},"y":{"a":0,"k":264.925,"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[34.95,34.95,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.4,0.4],"y":[0,0]},"t":80,"s":[10,10]},{"t":93,"s":[8,8]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.117647059262,0.556862771511,0.243137255311,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":112,"st":10,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[208.25,164,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[113.25,113.25,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":1500,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 2","parent":7,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1.987,3.029,0],"ix":2,"l":2},"a":{"a":0,"k":[-1.918,38.018,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[113,35],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-1.918,97.68],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":116,"op":395,"st":35,"bm":0},{"ddd":0,"ind":9,"ty":2,"nm":"Glow","parent":7,"tt":1,"refId":"image_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":139,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":155,"s":[35]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":210,"s":[35]},{"t":235,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":-1.987,"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.795],"y":[1]},"o":{"x":[0.176],"y":[0.073]},"t":139,"s":[108.726]},{"i":{"x":[0.807],"y":[1]},"o":{"x":[0.307],"y":[0]},"t":155,"s":[81]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":210,"s":[81]},{"t":235,"s":[109]}],"ix":4}},"a":{"a":0,"k":[401.5,239.5,0],"ix":1,"l":2},"s":{"a":0,"k":[36.111,36.222,100],"ix":6,"l":2}},"ao":0,"ip":116,"op":395,"st":35,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte","parent":7,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1.918,38.518,0],"ix":2,"l":2},"a":{"a":0,"k":[-1.918,38.018,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[112.836,115.964],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-1.918,38.393],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":116,"op":395,"st":35,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"NGA Line Outlines","parent":7,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1.5,80.379,0],"ix":2,"l":2},"a":{"a":0,"k":[45.896,0.896,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.4,"y":0},"t":115,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[96.146,1.016],[118.646,1.016]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.6,"y":0},"t":139,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[42.387,0.911],[63.59,0.911]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":155,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[42.385,0.887],[70.714,0.923]],"c":false}]},{"i":{"x":1,"y":1},"o":{"x":0.849,"y":0},"t":210,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[42.416,0.911],[70.714,0.923]],"c":false}]},{"t":235,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[96.146,1.016],[118.646,1.016]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.259000003338,0.522000014782,0.957000017166,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.793,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Yellow","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.4,"y":0},"t":115,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[118.646,1.016],[141.146,1.016]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.6,"y":0},"t":139,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[63.59,0.911],[87.443,0.911]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":155,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[70.714,0.923],[98.844,0.923]],"c":false}]},{"i":{"x":1,"y":1},"o":{"x":0.85,"y":0},"t":210,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[70.714,0.923],[98.844,0.923]],"c":false}]},{"t":235,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[118.646,1.016],[141.146,1.016]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.259000003338,0.522000014782,0.957000017166,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.793,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Green","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.4,"y":0},"t":115,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-32.104,1.016],[-9.604,1.016]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.6,"y":0},"t":139,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[21.184,0.911],[42.387,0.911]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":155,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[14.13,0.887],[42.385,0.887]],"c":false}]},{"i":{"x":1,"y":1},"o":{"x":0.85,"y":0},"t":210,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[14.13,0.887],[42.416,0.911]],"c":false}]},{"t":235,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-32.104,1.016],[-9.604,1.016]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.259000003338,0.522000014782,0.957000017166,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.793,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Red","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.4,"y":0},"t":115,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-54.604,1.016],[-32.104,1.016]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.6,"y":0},"t":139,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.972,0.911],[21.184,0.911]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":155,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-14.06,0.911],[14.13,0.887]],"c":false}]},{"i":{"x":1,"y":1},"o":{"x":0.85,"y":0},"t":210,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-14.06,0.911],[14.13,0.887]],"c":false}]},{"t":235,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-54.604,1.016],[-32.104,1.016]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.258999992819,0.522000002394,0.957000014361,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.793,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Blue","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":115,"op":236,"st":35,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Nav Bar Icons_Grey500","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,264.863,0],"ix":2,"l":2},"a":{"a":0,"k":[206,264.863,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.506,0],[0,0],[0,0.506],[0,0],[-0.506,0],[0,0],[0,-0.506],[0,0]],"o":[[0,0],[-0.506,0],[0,0],[0,-0.506],[0,0],[0.506,0],[0,0],[0,0.506]],"v":[[1.932,2.848],[-1.932,2.848],[-2.848,1.932],[-2.848,-1.932],[-1.932,-2.848],[1.932,-2.848],[2.848,-1.932],[2.848,1.932]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.603921592236,0.627451002598,0.65098041296,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[244.825,264.863],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0.372],[0,0],[0.314,-0.2],[0,0],[-0.291,-0.185],[0,0]],"o":[[0,0],[0,-0.372],[0,0],[-0.291,0.185],[0,0],[0.314,0.2]],"v":[[2.338,2.376],[2.338,-2.376],[1.613,-2.773],[-2.12,-0.398],[-2.12,0.398],[1.613,2.773]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.603921592236,0.627451002598,0.65098041296,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[166.665,264.863],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[166.665,264.863],"ix":2},"a":{"a":0,"k":[166.665,264.863],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nav Bar_White","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,264.863,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[4.1,0],[0,0],[0,4.1],[0,0],[0,0],[0,0]],"o":[[0,0],[-4.1,0],[0,0],[0,0],[0,0],[0,4.1]],"v":[[56.764,8.872],[-56.764,8.872],[-64.188,1.448],[-64.188,-8.872],[64.188,-8.872],[64.188,1.448]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Mic","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":122,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":129,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":228,"s":[100]},{"t":235,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":115,"s":[206,240.5,0],"to":[0,-15.083,0],"ti":[0,15.083,0]},{"i":{"x":1,"y":1},"o":{"x":0.167,"y":0.167},"t":155,"s":[206,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.65,"y":0},"t":210,"s":[206,150,0],"to":[0,7.667,0],"ti":[0,-7.667,0]},{"t":235,"s":[206,196,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.636,0],[0,4.636],[0,0],[-5.694,-0.823],[0,0],[0,0],[0,0],[0,5.93]],"o":[[0,4.636],[-4.636,0],[0,0],[0,5.93],[0,0],[0,0],[0,0],[5.694,-0.823],[0,0]],"v":[[8.399,61.968],[0,70.367],[-8.399,61.968],[-11.758,61.968],[-1.68,73.592],[-1.68,78.766],[1.68,78.766],[1.68,73.592],[11.758,61.968]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-2.788,0],[0,2.788],[0,0],[2.788,0],[0,-2.788],[0,0]],"o":[[2.788,0],[0,0],[0,-2.788],[-2.788,0],[0,0],[0,2.788]],"v":[[0,67.007],[5.039,61.968],[5.039,51.89],[0,46.85],[-5.039,51.89],[-5.039,61.968]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.101960785687,0.450980395079,0.909803926945,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":70,"op":1534,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Bottom Sheet","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":110,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":118.334,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":231.666,"s":[100]},{"t":240,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,273.699,0],"ix":2,"l":2},"a":{"a":0,"k":[0,48,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.4,"y":0},"t":110,"s":[{"i":[[0,0],[5.243,0],[0,0],[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045]],"o":[[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045],[0,0],[5.243,0],[0,0]],"v":[[64.188,38.773],[54.679,47.923],[-54.679,47.923],[-64.188,38.773],[-64.25,38.727],[-54.741,29.577],[54.617,29.577],[64.126,38.727]],"c":true}]},{"i":{"x":1,"y":1},"o":{"x":0.167,"y":0},"t":143,"s":[{"i":[[0,0],[5.243,0],[0,0],[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045]],"o":[[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045],[0,0],[5.243,0],[0,0]],"v":[[64.188,38.773],[54.679,47.923],[-54.679,47.923],[-64.188,38.773],[-64.188,-38.773],[-54.679,-47.923],[54.679,-47.923],[64.188,-38.773]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.65,"y":0},"t":215,"s":[{"i":[[0,0],[5.243,0],[0,0],[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045]],"o":[[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045],[0,0],[5.243,0],[0,0]],"v":[[64.188,38.773],[54.679,47.923],[-54.679,47.923],[-64.188,38.773],[-64.188,-38.773],[-54.679,-47.923],[54.679,-47.923],[64.188,-38.773]],"c":true}]},{"t":240,"s":[{"i":[[0,0],[5.243,0],[0,0],[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045]],"o":[[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045],[0,0],[5.243,0],[0,0]],"v":[[64.188,38.773],[54.679,47.923],[-54.679,47.923],[-64.188,38.773],[-64.25,38.727],[-54.741,29.577],[54.617,29.577],[64.126,38.727]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":70,"op":1534,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"Device Frame","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[5.243,0],[0,0],[0,5.244],[0,0],[-5.243,0],[0,0],[0,-5.244]],"o":[[0,5.244],[0,0],[-5.243,0],[0,0],[0,-5.244],[0,0],[5.243,0],[0,0]],"v":[[64.188,114.112],[54.679,123.622],[-54.679,123.622],[-64.188,114.112],[-64.188,-114.112],[-54.679,-123.622],[54.679,-123.622],[64.188,-114.112]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[6.554,0],[0,0],[0,-6.555],[0,0],[-6.554,0],[0,0],[0,6.555],[0,0],[0,1.313],[0,0],[1.313,0]],"o":[[0,-6.555],[0,0],[-6.554,0],[0,0],[0,6.555],[0,0],[6.554,0],[0,0],[1.313,0],[0,0],[0,-1.313],[0,0]],"v":[[66.566,-114.112],[54.679,-126],[-54.679,-126],[-66.566,-114.112],[-66.566,114.112],[-54.679,126],[54.679,126],[66.566,114.112],[66.566,-2.378],[68.943,-4.755],[68.943,-28.528],[66.566,-30.906]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901969433,0.86274510622,0.878431379795,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"Power Button","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":206,"ix":3},"y":{"a":0,"k":150,"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,1.313],[0,0],[1.313,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,-1.313],[0,0],[0,0],[0,0],[1.313,0]],"v":[[68.943,-52.302],[68.943,-61.811],[66.566,-64.188],[65.456,-64.188],[65.55,-49.906],[66.566,-49.924]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901969433,0.86274510622,0.878431379795,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1534,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":"Device Screen","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[5.243,0],[0,0],[0,5.244],[0,0],[-5.243,0],[0,0],[0,-5.244]],"o":[[0,5.244],[0,0],[-5.243,0],[0,0],[0,-5.244],[0,0],[5.243,0],[0,0]],"v":[[64.188,114.112],[54.679,123.622],[-54.679,123.622],[-64.188,114.112],[-64.188,-114.112],[-54.679,-123.622],[54.679,-123.622],[64.188,-114.112]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 5ebaeed81c9..469f20198e6 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -1220,14 +1220,12 @@ @string/screensaver_settings_summary_sleep @string/screensaver_settings_summary_dock @string/screensaver_settings_summary_either_long - @string/screensaver_settings_summary_never while_charging_only while_docked_only either_charging_or_docked - never diff --git a/res/values/strings.xml b/res/values/strings.xml index 5e654f96ef2..383d977ce83 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3168,6 +3168,8 @@ Try different styles, wallpapers, and more Screen saver + + Use screen saver While charging or docked @@ -5552,11 +5554,27 @@ Use %1$s Open %1$s - + %1$s added to Quick Settings. Swipe down to turn it on or off anytime. - + You can also add %1$s to Quick Settings from the top of your screen - + + Color correction added to Quick Settings. Swipe down to turn it on or off anytime. + + You can also add color correction to Quick Settings from the top of your screen + + Color inversion added to Quick Settings. Swipe down to turn it on or off anytime. + + You can also add color inversion to Quick Settings from the top of your screen + + Extra dim added to Quick Settings. Swipe down to turn it on or off anytime. + + You can also add extra dim to Quick Settings from the top of your screen + + One-handed mode added to Quick Settings. Swipe down to turn it on or off anytime. + + You can also add one-handed mode to Quick Settings from the top of your screen + Dismiss Adjust how colors display on your phone @@ -5617,10 +5635,10 @@ Audio adjustment - Audio Description + Audio description - Select audio sound track with audio description by default + Hear a description of what\u2019s happening on screen in supported movies and shows audio description, audio, description, low vision, @@ -11791,7 +11809,7 @@ Swipe up from a bottom corner to invoke digital assistant app. - Hold Home to invoke assistant + Hold Home for Assistant Press and hold the Home button to invoke digital assistant app. diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml index 2e253e2342a..509aed6c4d0 100644 --- a/res/xml/accessibility_settings.xml +++ b/res/xml/accessibility_settings.xml @@ -69,16 +69,6 @@ settings:keywords="@string/keywords_magnification" settings:controller="com.android.settings.accessibility.MagnificationPreferenceController"/> - - + + - + + - - - + diff --git a/res/xml/dream_fragment_overview.xml b/res/xml/dream_fragment_overview.xml index 105cec47cc7..0ca4869865b 100644 --- a/res/xml/dream_fragment_overview.xml +++ b/res/xml/dream_fragment_overview.xml @@ -19,26 +19,35 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" android:title="@string/screensaver_settings_title"> - - - + - - + android:key="dream_main_category"> + + + + + + + + diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 37d4a4e99eb..d258cc2fcc3 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -144,8 +144,7 @@ public class SettingsActivity extends SettingsBaseActivity public static final String EXTRA_SHOW_FRAGMENT_AS_SUBSETTING = ":settings:show_fragment_as_subsetting"; - public static final String EXTRA_IS_SECONDARY_LAYER_PAGE = - ":settings:is_secondary_layer_page"; + public static final String EXTRA_IS_SECOND_LAYER_PAGE = ":settings:is_second_layer_page"; /** * Additional extra of Settings#ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK. @@ -372,12 +371,12 @@ public class SettingsActivity extends SettingsBaseActivity if (WizardManagerHelper.isAnySetupWizard(intent)) { return false; } - final boolean isSecondaryLayerPage = - intent.getBooleanExtra(EXTRA_IS_SECONDARY_LAYER_PAGE, false); + final boolean isSecondLayerPage = + intent.getBooleanExtra(EXTRA_IS_SECOND_LAYER_PAGE, false); // TODO: move Settings's ActivityEmbeddingUtils to SettingsLib. return !com.android.settingslib.activityembedding.ActivityEmbeddingUtils - .shouldHideBackButton(this, isSecondaryLayerPage); + .shouldHideNavigateUpButton(this, isSecondLayerPage); } private boolean isSubSettings(Intent intent) { diff --git a/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java new file mode 100644 index 00000000000..33b6deb82b9 --- /dev/null +++ b/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.accessibility; + +import android.content.ComponentName; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; + +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.TogglePreferenceController; +import com.android.settingslib.PrimarySwitchPreference; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnCreate; +import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState; + +/** PrimarySwitchPreferenceController that shows quick settings tooltip on first use. */ +public abstract class AccessibilityQuickSettingsPrimarySwitchPreferenceController + extends TogglePreferenceController + implements LifecycleObserver, OnCreate, OnSaveInstanceState { + private static final String KEY_SAVED_QS_TOOLTIP_RESHOW = "qs_tooltip_reshow"; + private final Handler mHandler; + private PrimarySwitchPreference mPreference; + private AccessibilityQuickSettingsTooltipWindow mTooltipWindow; + private boolean mNeedsQSTooltipReshow = false; + + /** Returns the accessibility tile component name. */ + abstract ComponentName getTileComponentName(); + + /** Returns the accessibility tile tooltip content. */ + abstract CharSequence getTileTooltipContent(); + + public AccessibilityQuickSettingsPrimarySwitchPreferenceController(Context context, + String preferenceKey) { + super(context, preferenceKey); + mHandler = new Handler(context.getMainLooper()); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + // Restore the tooltip. + if (savedInstanceState != null) { + if (savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_RESHOW)) { + mNeedsQSTooltipReshow = savedInstanceState.getBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW); + } + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + if (mTooltipWindow != null) { + outState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, mTooltipWindow.isShowing()); + } + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + if (mNeedsQSTooltipReshow) { + mHandler.post(this::showQuickSettingsTooltipIfNeeded); + } + } + + @Override + public boolean setChecked(boolean isChecked) { + if (isChecked) { + showQuickSettingsTooltipIfNeeded(); + } + return isChecked; + } + + @Override + public boolean isChecked() { + return false; + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public int getSliceHighlightMenuRes() { + return R.string.menu_key_accessibility; + } + + private void showQuickSettingsTooltipIfNeeded() { + final ComponentName tileComponentName = getTileComponentName(); + if (tileComponentName == null) { + // Returns if no tile service assigned. + return; + } + + if (!mNeedsQSTooltipReshow && AccessibilityQuickSettingUtils.hasValueInSharedPreferences( + mContext, tileComponentName)) { + // Returns if quick settings tooltip only show once. + return; + } + + mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(mContext); + mTooltipWindow.setup(getTileTooltipContent(), + R.drawable.accessibility_auto_added_qs_tooltips_illustration); + mTooltipWindow.showAtTopCenter(mPreference.getSwitch()); + AccessibilityQuickSettingUtils.optInValueToSharedPreferences(mContext, tileComponentName); + mNeedsQSTooltipReshow = false; + } +} diff --git a/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java b/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java index 2c77102cc32..6b6872f9275 100644 --- a/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java +++ b/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java @@ -80,7 +80,7 @@ public class AccessibilityQuickSettingsTooltipWindow extends PopupWindow { * @param text text to be displayed * @param imageResId the resource ID of the image drawable */ - public void setup(String text, @DrawableRes int imageResId) { + public void setup(CharSequence text, @DrawableRes int imageResId) { this.setup(text, imageResId, /* closeDelayTimeMillis= */ 0); } @@ -94,7 +94,7 @@ public class AccessibilityQuickSettingsTooltipWindow extends PopupWindow { * @param imageResId the resource ID of the image drawable * @param closeDelayTimeMillis how long the popup window be auto-closed */ - public void setup(String text, @DrawableRes int imageResId, long closeDelayTimeMillis) { + public void setup(CharSequence text, @DrawableRes int imageResId, long closeDelayTimeMillis) { this.mCloseDelayTimeMillis = closeDelayTimeMillis; setBackgroundDrawable(new ColorDrawable(mContext.getColor(android.R.color.transparent))); diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java index 59618d643fd..9c54a0c8fc5 100644 --- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java +++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java @@ -83,8 +83,8 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF /** Returns the accessibility tile component name. */ protected abstract ComponentName getTileComponentName(); - /** Returns the accessibility tile feature name. */ - protected abstract CharSequence getTileName(); + /** Returns the accessibility tile tooltip content. */ + protected abstract CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type); @Override public void onCreate(Bundle savedInstanceState) { @@ -148,7 +148,7 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - // Reshow tooltips when activity recreate, such as rotate device. + // Reshow tooltip when activity recreate, such as rotate device. if (mNeedsQSTooltipReshow) { getView().post(this::showQuickSettingsTooltipIfNeeded); } @@ -499,21 +499,17 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF return; } - final CharSequence tileName = getTileName(); - if (TextUtils.isEmpty(tileName)) { - // Returns if no title of tile service assigned. + final CharSequence content = getTileTooltipContent(mNeedsQSTooltipType); + if (TextUtils.isEmpty(content)) { + // Returns if no content of tile tooltip assigned. return; } - final int titleResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT - ? R.string.accessibility_service_qs_tooltips_content - : R.string.accessibility_service_auto_added_qs_tooltips_content; - final String title = getString(titleResId, tileName); final int imageResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT ? R.drawable.accessibility_qs_tooltips_illustration : R.drawable.accessibility_auto_added_qs_tooltips_illustration; mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(getContext()); - mTooltipWindow.setup(title, imageResId); + mTooltipWindow.setup(content, imageResId); mTooltipWindow.showAtTopCenter(getView()); AccessibilityQuickSettingUtils.optInValueToSharedPreferences(getContext(), tileComponentName); diff --git a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java index b04582f2023..036b2ea755e 100644 --- a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java +++ b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java @@ -41,6 +41,7 @@ import androidx.annotation.Nullable; import androidx.preference.Preference; import com.android.settings.R; +import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType; import com.android.settings.overlay.FeatureFactory; import java.util.ArrayList; @@ -128,12 +129,21 @@ public class LaunchAccessibilityActivityPreferenceFragment extends ToggleFeature } @Override - CharSequence getTileName() { + CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) { final ComponentName componentName = getTileComponentName(); if (componentName == null) { return null; } - return loadTileLabel(getPrefContext(), componentName); + + final CharSequence tileName = loadTileLabel(getPrefContext(), componentName); + if (tileName == null) { + return null; + } + + final int titleResId = type == QuickSettingsTooltipType.GUIDE_TO_EDIT + ? R.string.accessibility_service_qs_tooltips_content + : R.string.accessibility_service_auto_added_qs_tooltips_content; + return getString(titleResId, tileName); } @Override diff --git a/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java b/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java index 2018e059693..7b40024ca54 100644 --- a/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java +++ b/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java @@ -16,6 +16,9 @@ package com.android.settings.accessibility; +import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_TILE_SERVICE_COMPONENT_NAME; + +import android.content.ComponentName; import android.content.Context; import android.database.ContentObserver; import android.hardware.display.ColorDisplayManager; @@ -30,14 +33,14 @@ import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.core.TogglePreferenceController; import com.android.settingslib.PrimarySwitchPreference; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; /** PreferenceController that shows the Reduce Bright Colors summary */ -public class ReduceBrightColorsPreferenceController extends TogglePreferenceController +public class ReduceBrightColorsPreferenceController + extends AccessibilityQuickSettingsPrimarySwitchPreferenceController implements LifecycleObserver, OnStart, OnStop { private ContentObserver mSettingsContentObserver; private PrimarySwitchPreference mPreference; @@ -67,6 +70,7 @@ public class ReduceBrightColorsPreferenceController extends TogglePreferenceCont @Override public boolean setChecked(boolean isChecked) { + super.setChecked(isChecked); return mColorDisplayManager.setReduceBrightColorsActivated(isChecked); } @@ -105,8 +109,20 @@ public class ReduceBrightColorsPreferenceController extends TogglePreferenceCont Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED), false, mSettingsContentObserver, UserHandle.USER_CURRENT); } + @Override public void onStop() { mContext.getContentResolver().unregisterContentObserver(mSettingsContentObserver); } + + @Override + protected ComponentName getTileComponentName() { + return REDUCE_BRIGHT_COLORS_TILE_SERVICE_COMPONENT_NAME; + } + + @Override + CharSequence getTileTooltipContent() { + return mContext.getText( + R.string.accessibility_reduce_bright_colors_auto_added_qs_tooltip_content); + } } diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java index 02da51e5a59..1a63f1fc9b8 100644 --- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java @@ -47,6 +47,7 @@ import android.widget.Switch; import androidx.annotation.Nullable; import com.android.settings.R; +import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType; import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.accessibility.AccessibilityUtils; @@ -239,12 +240,21 @@ public class ToggleAccessibilityServicePreferenceFragment extends } @Override - CharSequence getTileName() { + CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) { final ComponentName componentName = getTileComponentName(); if (componentName == null) { return null; } - return loadTileLabel(getPrefContext(), componentName); + + final CharSequence tileName = loadTileLabel(getPrefContext(), componentName); + if (tileName == null) { + return null; + } + + final int titleResId = type == QuickSettingsTooltipType.GUIDE_TO_EDIT + ? R.string.accessibility_service_qs_tooltips_content + : R.string.accessibility_service_auto_added_qs_tooltips_content; + return getString(titleResId, tileName); } @Override diff --git a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java index 1f498d60af9..58837147969 100644 --- a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java @@ -144,8 +144,10 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere } @Override - CharSequence getTileName() { - return getText(R.string.accessibility_display_inversion_preference_title); + CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) { + return getText(type == QuickSettingsTooltipType.GUIDE_TO_EDIT + ? R.string.accessibility_color_inversion_qs_tooltip_content + : R.string.accessibility_color_inversion_auto_added_qs_tooltip_content); } @Override diff --git a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java index c4df5bf7503..183da964cfc 100644 --- a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java @@ -201,8 +201,10 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe } @Override - CharSequence getTileName() { - return getText(R.string.accessibility_display_daltonizer_preference_title); + CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) { + return getText(type == QuickSettingsTooltipType.GUIDE_TO_EDIT + ? R.string.accessibility_color_correction_qs_tooltip_content + : R.string.accessibility_color_correction_auto_added_qs_tooltip_content); } @Override diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java index 69b8f75c060..9738321fc0c 100644 --- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java @@ -222,7 +222,7 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference updatePreferenceOrder(); - // Reshow tooltips when activity recreate, such as rotate device. + // Reshow tooltip when activity recreate, such as rotate device. if (mNeedsQSTooltipReshow) { getView().post(this::showQuickSettingsTooltipIfNeeded); } @@ -331,8 +331,8 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference /** Returns the accessibility tile component name. */ abstract ComponentName getTileComponentName(); - /** Returns the accessibility tile feature name. */ - abstract CharSequence getTileName(); + /** Returns the accessibility tile tooltip content. */ + abstract CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type); protected void updateToggleServiceTitle(SettingsMainSwitchPreference switchPreference) { final CharSequence title = @@ -870,21 +870,17 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference return; } - final CharSequence tileName = getTileName(); - if (TextUtils.isEmpty(tileName)) { - // Returns if no title of tile service assigned. + final CharSequence content = getTileTooltipContent(mNeedsQSTooltipType); + if (TextUtils.isEmpty(content)) { + // Returns if no content of tile tooltip assigned. return; } - final int titleResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT - ? R.string.accessibility_service_qs_tooltips_content - : R.string.accessibility_service_auto_added_qs_tooltips_content; - final String title = getString(titleResId, tileName); final int imageResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT ? R.drawable.accessibility_qs_tooltips_illustration : R.drawable.accessibility_auto_added_qs_tooltips_illustration; mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(getContext()); - mTooltipWindow.setup(title, imageResId); + mTooltipWindow.setup(content, imageResId); mTooltipWindow.showAtTopCenter(getView()); AccessibilityQuickSettingUtils.optInValueToSharedPreferences(getContext(), tileComponentName); diff --git a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java index fb9c4a87ed1..93884b766ea 100644 --- a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java @@ -184,8 +184,10 @@ public class ToggleReduceBrightColorsPreferenceFragment extends ToggleFeaturePre } @Override - CharSequence getTileName() { - return getText(R.string.reduce_bright_colors_preference_title); + CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) { + return getText(type == QuickSettingsTooltipType.GUIDE_TO_EDIT + ? R.string.accessibility_reduce_bright_colors_qs_tooltip_content + : R.string.accessibility_reduce_bright_colors_auto_added_qs_tooltip_content); } @Override diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java index 62f42820401..1176fa462c0 100644 --- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java @@ -47,6 +47,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.settings.DialogCreatable; import com.android.settings.R; import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType; +import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType; import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; import com.android.settings.utils.LocaleUtils; @@ -405,7 +406,7 @@ public class ToggleScreenMagnificationPreferenceFragment extends } @Override - CharSequence getTileName() { + CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) { return null; } diff --git a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java index dee24dfefb4..124bb4f2707 100644 --- a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java +++ b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java @@ -197,7 +197,7 @@ public class ActivityEmbeddingRulesController { addActivityFilter(activityFilters, Settings.class); final Intent intent = new Intent(mContext, Settings.NetworkDashboardActivity.class); - intent.putExtra(SettingsActivity.EXTRA_IS_SECONDARY_LAYER_PAGE, true); + intent.putExtra(SettingsActivity.EXTRA_IS_SECOND_LAYER_PAGE, true); final SplitPlaceholderRule placeholderRule = new SplitPlaceholderRule( activityFilters, intent, diff --git a/src/com/android/settings/core/SubSettingLauncher.java b/src/com/android/settings/core/SubSettingLauncher.java index 93a939febf1..e8c42197607 100644 --- a/src/com/android/settings/core/SubSettingLauncher.java +++ b/src/com/android/settings/core/SubSettingLauncher.java @@ -122,9 +122,9 @@ public class SubSettingLauncher { return this; } - /** Decide whether the next page is secondary layer page or not. */ - public SubSettingLauncher setIsSecondaryLayerPage(boolean isSecondaryLayerPage) { - mLaunchRequest.mIsSecondaryLayerPage = isSecondaryLayerPage; + /** Decide whether the next page is second layer page or not. */ + public SubSettingLauncher setIsSecondLayerPage(boolean isSecondLayerPage) { + mLaunchRequest.mIsSecondLayerPage = isSecondLayerPage; return this; } @@ -176,8 +176,8 @@ public class SubSettingLauncher { intent.addFlags(mLaunchRequest.mFlags); intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE, mLaunchRequest.mTransitionType); - intent.putExtra(SettingsActivity.EXTRA_IS_SECONDARY_LAYER_PAGE, - mLaunchRequest.mIsSecondaryLayerPage); + intent.putExtra(SettingsActivity.EXTRA_IS_SECOND_LAYER_PAGE, + mLaunchRequest.mIsSecondLayerPage); return intent; } @@ -225,6 +225,6 @@ public class SubSettingLauncher { int mTransitionType; Bundle mArguments; Bundle mExtras; - boolean mIsSecondaryLayerPage; + boolean mIsSecondLayerPage; } } diff --git a/src/com/android/settings/development/featureflags/FeatureFlagPreference.java b/src/com/android/settings/development/featureflags/FeatureFlagPreference.java index 992aa0f6726..08ae760684b 100644 --- a/src/com/android/settings/development/featureflags/FeatureFlagPreference.java +++ b/src/com/android/settings/development/featureflags/FeatureFlagPreference.java @@ -52,10 +52,10 @@ public class FeatureFlagPreference extends SwitchPreference { FeatureFlagUtils.setEnabled(getContext(), mKey, isChecked); } - // A temporary logic for settings_hide_secondary_page_back_button_in_two_pane + // A temporary logic for settings_hide_second_layer_page_navigate_up_button_in_two_pane // Remove it before Android T release. if (TextUtils.equals(mKey, - FeatureFlagUtils.SETTINGS_HIDE_SECONDARY_PAGE_BACK_BUTTON_IN_TWO_PANE)) { + FeatureFlagUtils.SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE)) { Settings.Global.putString(getContext().getContentResolver(), mKey, String.valueOf(isChecked)); } diff --git a/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java b/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java index c8f6280fe3b..beefc054cd0 100644 --- a/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java +++ b/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java @@ -22,6 +22,7 @@ import static androidx.lifecycle.Lifecycle.Event.ON_STOP; import android.app.settings.SettingsEnums; import android.content.Context; +import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.OnLifecycleEvent; @@ -51,16 +52,24 @@ public class DeviceStateAutoRotateSettingController extends TogglePreferenceCont private final String mDeviceStateDescription; private final MetricsFeatureProvider mMetricsFeatureProvider; - public DeviceStateAutoRotateSettingController(Context context, int deviceState, - String deviceStateDescription, int order) { + @VisibleForTesting + DeviceStateAutoRotateSettingController(Context context, int deviceState, + String deviceStateDescription, int order, + MetricsFeatureProvider metricsFeatureProvider) { super(context, getPreferenceKeyForDeviceState(deviceState)); - mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); + mMetricsFeatureProvider = metricsFeatureProvider; mDeviceState = deviceState; mDeviceStateDescription = deviceStateDescription; mAutoRotateSettingsManager = DeviceStateRotationLockSettingsManager.getInstance(context); mOrder = order; } + public DeviceStateAutoRotateSettingController(Context context, int deviceState, + String deviceStateDescription, int order) { + this(context, deviceState, deviceStateDescription, order, + FeatureFactory.getFactory(context).getMetricsFeatureProvider()); + } + void init(Lifecycle lifecycle) { lifecycle.addObserver(this); } @@ -108,12 +117,22 @@ public class DeviceStateAutoRotateSettingController extends TogglePreferenceCont @Override public boolean setChecked(boolean isChecked) { boolean isRotationLocked = !isChecked; - mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATION_LOCK, - isRotationLocked); + logSettingChanged(isChecked); mAutoRotateSettingsManager.updateSetting(mDeviceState, isRotationLocked); return true; } + private void logSettingChanged(boolean isChecked) { + boolean isRotationLocked = !isChecked; + mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATION_LOCK, + isRotationLocked); + + int actionCategory = isChecked + ? SettingsEnums.ACTION_ENABLE_AUTO_ROTATION_DEVICE_STATE + : SettingsEnums.ACTION_DISABLE_AUTO_ROTATION_DEVICE_STATE; + mMetricsFeatureProvider.action(mContext, actionCategory, /* value= */ mDeviceState); + } + @Override public void updateRawDataToIndex(List rawData) { SearchIndexableRaw indexable = new SearchIndexableRaw(mContext); diff --git a/src/com/android/settings/dream/DreamAdapter.java b/src/com/android/settings/dream/DreamAdapter.java index f196500af5c..27c32dfbe79 100644 --- a/src/com/android/settings/dream/DreamAdapter.java +++ b/src/com/android/settings/dream/DreamAdapter.java @@ -32,6 +32,7 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; +import com.android.settingslib.utils.ColorUtil; import java.util.List; @@ -43,17 +44,20 @@ public class DreamAdapter extends RecyclerView.Adapter @LayoutRes private final int mLayoutRes; private int mLastSelectedPos = -1; + private boolean mEnabled = true; /** * View holder for each {@link IDreamItem}. */ private class DreamViewHolder extends RecyclerView.ViewHolder { + private static final int VALUE_ENABLED_ALPHA = 255; private final TextView mTitleView; private final TextView mSummaryView; private final ImageView mPreviewView; private final ImageView mPreviewPlaceholderView; private final Button mCustomizeButton; private final Context mContext; + private final int mDisabledAlphaValue; DreamViewHolder(View view, Context context) { super(view); @@ -63,6 +67,7 @@ public class DreamAdapter extends RecyclerView.Adapter mTitleView = view.findViewById(R.id.title_text); mSummaryView = view.findViewById(R.id.summary_text); mCustomizeButton = view.findViewById(R.id.customize_button); + mDisabledAlphaValue = (int) (ColorUtil.getDisabledAlpha(context) * VALUE_ENABLED_ALPHA); } /** @@ -88,10 +93,11 @@ public class DreamAdapter extends RecyclerView.Adapter mPreviewView.setImageDrawable(null); mPreviewPlaceholderView.setVisibility(View.VISIBLE); } + mPreviewView.setImageAlpha(getAlpha()); final Drawable icon = item.isActive() ? mContext.getDrawable(R.drawable.ic_dream_check_circle) - : item.getIcon(); + : item.getIcon().mutate(); if (icon instanceof VectorDrawable) { icon.setTintList( mContext.getColorStateList(R.color.dream_card_icon_color_state_list)); @@ -99,6 +105,7 @@ public class DreamAdapter extends RecyclerView.Adapter final int iconSize = mContext.getResources().getDimensionPixelSize( R.dimen.dream_item_icon_size); icon.setBounds(0, 0, iconSize, iconSize); + icon.setAlpha(getAlpha()); mTitleView.setCompoundDrawablesRelative(icon, null, null, null); if (item.isActive()) { @@ -109,7 +116,8 @@ public class DreamAdapter extends RecyclerView.Adapter } mCustomizeButton.setOnClickListener(v -> item.onCustomizeClicked()); - mCustomizeButton.setVisibility(item.allowCustomization() ? View.VISIBLE : View.GONE); + mCustomizeButton.setVisibility( + item.allowCustomization() && mEnabled ? View.VISIBLE : View.GONE); itemView.setOnClickListener(v -> { item.onItemClicked(); @@ -118,6 +126,26 @@ public class DreamAdapter extends RecyclerView.Adapter } notifyItemChanged(position); }); + + setEnabledStateOnViews(itemView, mEnabled); + } + + private int getAlpha() { + return mEnabled ? VALUE_ENABLED_ALPHA : mDisabledAlphaValue; + } + + /** + * Makes sure the view (and any children) get the enabled state changed. + */ + private void setEnabledStateOnViews(@NonNull View v, boolean enabled) { + v.setEnabled(enabled); + + if (v instanceof ViewGroup) { + final ViewGroup vg = (ViewGroup) v; + for (int i = vg.getChildCount() - 1; i >= 0; i--) { + setEnabledStateOnViews(vg.getChildAt(i), enabled); + } + } } } @@ -143,4 +171,14 @@ public class DreamAdapter extends RecyclerView.Adapter public int getItemCount() { return mItemList.size(); } + + /** + * Sets the enabled state of all items. + */ + public void setEnabled(boolean enabled) { + if (mEnabled != enabled) { + mEnabled = enabled; + notifyDataSetChanged(); + } + } } diff --git a/src/com/android/settings/dream/DreamMainSwitchPreferenceController.java b/src/com/android/settings/dream/DreamMainSwitchPreferenceController.java new file mode 100644 index 00000000000..1425d3a7676 --- /dev/null +++ b/src/com/android/settings/dream/DreamMainSwitchPreferenceController.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.dream; + +import static androidx.lifecycle.Lifecycle.Event.ON_START; +import static androidx.lifecycle.Lifecycle.Event.ON_STOP; + +import android.content.Context; +import android.database.ContentObserver; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings; + +import androidx.lifecycle.OnLifecycleEvent; + +import com.android.settings.widget.SettingsMainSwitchPreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.dream.DreamBackend; + +/** + * Preference controller for switching dreams on/off. + */ +public class DreamMainSwitchPreferenceController extends + SettingsMainSwitchPreferenceController implements LifecycleObserver { + static final String MAIN_SWITCH_PREF_KEY = "dream_main_settings_switch"; + private final DreamBackend mBackend; + + private final ContentObserver mObserver = new ContentObserver( + new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange) { + updateState(mSwitchPreference); + } + }; + + public DreamMainSwitchPreferenceController(Context context, String key) { + super(context, key); + mBackend = DreamBackend.getInstance(context); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public boolean isChecked() { + return mBackend.isEnabled(); + } + + @Override + public boolean setChecked(boolean isChecked) { + mBackend.setEnabled(isChecked); + return true; + } + + @Override + public boolean isSliceable() { + return false; + } + + @Override + public int getSliceHighlightMenuRes() { + // not needed since it's not sliceable + return NO_RES; + } + + @OnLifecycleEvent(ON_START) + void onStart() { + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.SCREENSAVER_ENABLED), + /* notifyForDescendants= */ false, mObserver); + } + + @OnLifecycleEvent(ON_STOP) + void onStop() { + mContext.getContentResolver().unregisterContentObserver(mObserver); + } +} diff --git a/src/com/android/settings/dream/DreamPickerController.java b/src/com/android/settings/dream/DreamPickerController.java index 201d6de7f00..5afc4923567 100644 --- a/src/com/android/settings/dream/DreamPickerController.java +++ b/src/com/android/settings/dream/DreamPickerController.java @@ -16,11 +16,15 @@ package com.android.settings.dream; +import static com.android.settings.dream.DreamMainSwitchPreferenceController.MAIN_SWITCH_PREF_KEY; + import android.app.settings.SettingsEnums; import android.content.Context; import android.graphics.drawable.Drawable; +import android.widget.Switch; import androidx.annotation.Nullable; +import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import androidx.recyclerview.widget.RecyclerView; @@ -31,6 +35,8 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.dream.DreamBackend; import com.android.settingslib.dream.DreamBackend.DreamInfo; import com.android.settingslib.widget.LayoutPreference; +import com.android.settingslib.widget.MainSwitchPreference; +import com.android.settingslib.widget.OnMainSwitchChangeListener; import java.util.List; import java.util.stream.Collectors; @@ -38,8 +44,8 @@ import java.util.stream.Collectors; /** * Controller for the dream picker where the user can select a screensaver. */ -public class DreamPickerController extends BasePreferenceController { - private static final String KEY = "dream_picker"; +public class DreamPickerController extends BasePreferenceController implements + OnMainSwitchChangeListener { private final DreamBackend mBackend; private final MetricsFeatureProvider mMetricsFeatureProvider; @@ -48,23 +54,18 @@ public class DreamPickerController extends BasePreferenceController { private DreamInfo mActiveDream; private DreamAdapter mAdapter; - public DreamPickerController(Context context) { - this(context, DreamBackend.getInstance(context)); + public DreamPickerController(Context context, String key) { + this(context, key, DreamBackend.getInstance(context)); } - public DreamPickerController(Context context, DreamBackend backend) { - super(context, KEY); + public DreamPickerController(Context context, String key, DreamBackend backend) { + super(context, key); mBackend = backend; mDreamInfos = mBackend.getDreamInfos(); mActiveDream = getActiveDreamInfo(mDreamInfos); mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } - @Override - public String getPreferenceKey() { - return KEY; - } - @Override public int getAvailabilityStatus() { return mDreamInfos.size() > 0 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; @@ -79,6 +80,8 @@ public class DreamPickerController extends BasePreferenceController { .map(DreamItem::new) .collect(Collectors.toList())); + mAdapter.setEnabled(mBackend.isEnabled()); + final LayoutPreference pref = screen.findPreference(getPreferenceKey()); if (pref == null) { return; @@ -89,6 +92,11 @@ public class DreamPickerController extends BasePreferenceController { new GridSpacingItemDecoration(mContext, R.dimen.dream_preference_card_padding)); recyclerView.setHasFixedSize(true); recyclerView.setAdapter(mAdapter); + + final Preference mainSwitchPref = screen.findPreference(MAIN_SWITCH_PREF_KEY); + if (mainSwitchPref instanceof MainSwitchPreference) { + ((MainSwitchPreference) mainSwitchPref).addOnSwitchChangeListener(this); + } } @Nullable @@ -100,6 +108,13 @@ public class DreamPickerController extends BasePreferenceController { .orElse(null); } + @Override + public void onSwitchChanged(Switch switchView, boolean isChecked) { + if (mAdapter != null) { + mAdapter.setEnabled(isChecked); + } + } + private class DreamItem implements IDreamItem { DreamInfo mDreamInfo; diff --git a/src/com/android/settings/dream/DreamSettings.java b/src/com/android/settings/dream/DreamSettings.java index bfa19a9e91f..d30f50ff91b 100644 --- a/src/com/android/settings/dream/DreamSettings.java +++ b/src/com/android/settings/dream/DreamSettings.java @@ -16,6 +16,7 @@ package com.android.settings.dream; +import static com.android.settings.dream.DreamMainSwitchPreferenceController.MAIN_SWITCH_PREF_KEY; import static com.android.settingslib.dream.DreamBackend.EITHER; import static com.android.settingslib.dream.DreamBackend.NEVER; import static com.android.settingslib.dream.DreamBackend.WHILE_CHARGING; @@ -25,10 +26,13 @@ import android.app.settings.SettingsEnums; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; +import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.Switch; import androidx.annotation.VisibleForTesting; +import androidx.preference.PreferenceCategory; import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; @@ -38,12 +42,14 @@ import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.dream.DreamBackend; import com.android.settingslib.dream.DreamBackend.WhenToDream; import com.android.settingslib.search.SearchIndexable; +import com.android.settingslib.widget.MainSwitchPreference; +import com.android.settingslib.widget.OnMainSwitchChangeListener; import java.util.ArrayList; import java.util.List; @SearchIndexable -public class DreamSettings extends DashboardFragment { +public class DreamSettings extends DashboardFragment implements OnMainSwitchChangeListener { private static final String TAG = "DreamSettings"; static final String WHILE_CHARGING_ONLY = "while_charging_only"; @@ -51,6 +57,13 @@ public class DreamSettings extends DashboardFragment { static final String EITHER_CHARGING_OR_DOCKED = "either_charging_or_docked"; static final String NEVER_DREAM = "never"; + private static final String MAIN_PREF_CATEGORY = "dream_main_category"; + + private MainSwitchPreference mMainSwitchPreference; + private PreferenceCategory mMainPrefCategory; + private Button mPreviewButton; + private RecyclerView mRecyclerView; + @WhenToDream static int getSettingFromPrefKey(String key) { switch (key) { @@ -135,37 +148,58 @@ public class DreamSettings extends DashboardFragment { private static List buildPreferenceControllers(Context context) { final List controllers = new ArrayList<>(); - controllers.add(new DreamPickerController(context)); controllers.add(new WhenToDreamPreferenceController(context)); return controllers; } @Override - public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, - Bundle bundle) { - - final ViewGroup root = getActivity().findViewById(android.R.id.content); - final Button previewButton = (Button) getActivity().getLayoutInflater().inflate( - R.layout.dream_preview_button, root, false); - root.addView(previewButton); + public void onCreate(Bundle icicle) { + super.onCreate(icicle); final DreamBackend dreamBackend = DreamBackend.getInstance(getContext()); - previewButton.setOnClickListener(v -> dreamBackend.preview(dreamBackend.getActiveDream())); - final RecyclerView recyclerView = super.onCreateRecyclerView(inflater, parent, bundle); - previewButton.post(() -> { - recyclerView.setPadding(0, 0, 0, previewButton.getMeasuredHeight()); - }); - return recyclerView; + mMainSwitchPreference = findPreference(MAIN_SWITCH_PREF_KEY); + if (mMainSwitchPreference != null) { + mMainSwitchPreference.addOnSwitchChangeListener(this); + } + + mMainPrefCategory = findPreference(MAIN_PREF_CATEGORY); + if (mMainPrefCategory != null) { + mMainPrefCategory.setEnabled(dreamBackend.isEnabled()); + } } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER - = new BaseSearchIndexProvider(R.xml.dream_fragment_overview) { + @Override + public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, + Bundle bundle) { + final DreamBackend dreamBackend = DreamBackend.getInstance(getContext()); - @Override - public List createPreferenceControllers(Context context) { - return buildPreferenceControllers(context); - } - }; + final ViewGroup root = getActivity().findViewById(android.R.id.content); + mPreviewButton = (Button) getActivity().getLayoutInflater().inflate( + R.layout.dream_preview_button, root, false); + mPreviewButton.setVisibility(dreamBackend.isEnabled() ? View.VISIBLE : View.GONE); + root.addView(mPreviewButton); + mPreviewButton.setOnClickListener(v -> dreamBackend.preview(dreamBackend.getActiveDream())); + + mRecyclerView = super.onCreateRecyclerView(inflater, parent, bundle); + updatePaddingForPreviewButton(); + return mRecyclerView; + } + + private void updatePaddingForPreviewButton() { + mPreviewButton.post(() -> { + mRecyclerView.setPadding(0, 0, 0, mPreviewButton.getMeasuredHeight()); + }); + } + + @Override + public void onSwitchChanged(Switch switchView, boolean isChecked) { + mMainPrefCategory.setEnabled(isChecked); + mPreviewButton.setVisibility(isChecked ? View.VISIBLE : View.GONE); + updatePaddingForPreviewButton(); + } + + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider(R.xml.dream_fragment_overview); } diff --git a/src/com/android/settings/gestures/OneHandedSettings.java b/src/com/android/settings/gestures/OneHandedSettings.java index 0e6b402429d..13ccbd6919b 100644 --- a/src/com/android/settings/gestures/OneHandedSettings.java +++ b/src/com/android/settings/gestures/OneHandedSettings.java @@ -131,8 +131,10 @@ public class OneHandedSettings extends AccessibilityShortcutPreferenceFragment { } @Override - protected CharSequence getTileName() { - return mFeatureName; + protected CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) { + return type == QuickSettingsTooltipType.GUIDE_TO_EDIT + ? getText(R.string.accessibility_one_handed_mode_qs_tooltip_content) + : getText(R.string.accessibility_one_handed_mode_auto_added_qs_tooltip_content); } @Override diff --git a/src/com/android/settings/homepage/TopLevelSettings.java b/src/com/android/settings/homepage/TopLevelSettings.java index 734e079537d..7d578347e7e 100644 --- a/src/com/android/settings/homepage/TopLevelSettings.java +++ b/src/com/android/settings/homepage/TopLevelSettings.java @@ -119,7 +119,7 @@ public class TopLevelSettings extends DashboardFragment implements ? ((Instrumentable) caller).getMetricsCategory() : Instrumentable.METRICS_CATEGORY_UNKNOWN) .setTitleRes(-1) - .setIsSecondaryLayerPage(true) + .setIsSecondLayerPage(true) .launch(); return true; } diff --git a/src/com/android/settings/nearby/FastPairSettingsFragment.java b/src/com/android/settings/nearby/FastPairSettingsFragment.java index f605cf18f83..702e90a915f 100644 --- a/src/com/android/settings/nearby/FastPairSettingsFragment.java +++ b/src/com/android/settings/nearby/FastPairSettingsFragment.java @@ -21,6 +21,7 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.nearby.NearbyManager; import android.os.Bundle; import android.provider.Settings; import android.text.TextUtils; @@ -56,9 +57,9 @@ public class FastPairSettingsFragment extends SettingsPreferenceFragment { findPreference(SCAN_SWITCH_KEY)); mainSwitchPreference.addOnSwitchChangeListener( (switchView, isChecked) -> - Settings.Secure.putInt(getContentResolver(), - Settings.Secure.FAST_PAIR_SCAN_ENABLED, isChecked ? 1 : 0)); - mainSwitchPreference.setChecked(isFastPairScanAvailable()); + NearbyManager.setFastPairScanEnabled(getContext(), isChecked)); + mainSwitchPreference.setChecked( + NearbyManager.getFastPairScanEnabled(getContext(), false)); Preference savedDevicePref = Objects.requireNonNull( findPreference(SAVED_DEVICES_PREF_KEY)); @@ -89,11 +90,6 @@ public class FastPairSettingsFragment extends SettingsPreferenceFragment { public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.fast_pair_settings); - private boolean isFastPairScanAvailable() { - return Settings.Secure.getInt(getContentResolver(), - Settings.Secure.FAST_PAIR_SCAN_ENABLED, 1) != 0; - } - @Nullable private ComponentName getSavedDevicesComponent() { String savedDevicesComponent = Settings.Secure.getString( diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java index ea864eadbaf..faf5010b8e7 100644 --- a/src/com/android/settings/network/NetworkProviderSettings.java +++ b/src/com/android/settings/network/NetworkProviderSettings.java @@ -628,15 +628,7 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment } if (preference instanceof LongPressWifiEntryPreference) { - final WifiEntry selectedEntry = - ((LongPressWifiEntryPreference) preference).getWifiEntry(); - - if (selectedEntry.shouldEditBeforeConnect()) { - launchConfigNewNetworkFragment(selectedEntry); - return true; - } - - connect(selectedEntry, true /* editIfNoConfig */, true /* fullScreenEdit */); + onSelectedWifiPreferenceClick((LongPressWifiEntryPreference) preference); } else if (preference == mAddWifiNetworkPreference) { onAddNetworkPressed(); } else { @@ -645,6 +637,25 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment return true; } + @VisibleForTesting + void onSelectedWifiPreferenceClick(LongPressWifiEntryPreference preference) { + final WifiEntry selectedEntry = preference.getWifiEntry(); + + if (selectedEntry.shouldEditBeforeConnect()) { + launchConfigNewNetworkFragment(selectedEntry); + return; + } + + if (selectedEntry.canConnect()) { + connect(selectedEntry, true /* editIfNoConfig */, true /* fullScreenEdit */); + return; + } + + if (selectedEntry.isSaved()) { + launchNetworkDetailsFragment(preference); + } + } + private void launchWifiDppConfiguratorActivity(WifiEntry wifiEntry) { final Intent intent = WifiDppUtils.getConfiguratorQrCodeGeneratorIntentOrNull(getContext(), mWifiManager, wifiEntry); @@ -984,7 +995,8 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment return new FirstWifiEntryPreference(getPrefContext(), wifiEntry, this); } - private void launchNetworkDetailsFragment(LongPressWifiEntryPreference pref) { + @VisibleForTesting + void launchNetworkDetailsFragment(LongPressWifiEntryPreference pref) { final WifiEntry wifiEntry = pref.getWifiEntry(); final Context context = getContext(); final CharSequence title = @@ -1253,7 +1265,8 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment } } - private void launchConfigNewNetworkFragment(WifiEntry wifiEntry) { + @VisibleForTesting + void launchConfigNewNetworkFragment(WifiEntry wifiEntry) { final Bundle bundle = new Bundle(); bundle.putString(WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY, wifiEntry.getKey()); diff --git a/src/com/android/settings/network/PrivateDnsPreferenceController.java b/src/com/android/settings/network/PrivateDnsPreferenceController.java index 07d57140ec1..ed6f9ed955d 100644 --- a/src/com/android/settings/network/PrivateDnsPreferenceController.java +++ b/src/com/android/settings/network/PrivateDnsPreferenceController.java @@ -85,9 +85,12 @@ public class PrivateDnsPreferenceController extends BasePreferenceController @Override public int getAvailabilityStatus() { - return mContext.getResources().getBoolean(R.bool.config_show_private_dns_settings) - ? AVAILABLE - : UNSUPPORTED_ON_DEVICE; + if (!mContext.getResources().getBoolean(R.bool.config_show_private_dns_settings)) { + return UNSUPPORTED_ON_DEVICE; + } + final UserManager userManager = mContext.getSystemService(UserManager.class); + if (userManager.isGuestUser()) return DISABLED_FOR_USER; + return AVAILABLE; } @Override diff --git a/src/com/android/settings/notification/app/NotificationSettings.java b/src/com/android/settings/notification/app/NotificationSettings.java index 9dc0b595035..afc9a66716d 100644 --- a/src/com/android/settings/notification/app/NotificationSettings.java +++ b/src/com/android/settings/notification/app/NotificationSettings.java @@ -362,7 +362,8 @@ abstract public class NotificationSettings extends DashboardFragment { final String p = packages[i]; if (pkg.equals(p)) { try { - return mPm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES); + return mPm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES + | PackageManager.GET_PERMISSIONS); } catch (NameNotFoundException e) { Log.w(TAG, "Failed to load package " + pkg, e); } diff --git a/src/com/android/settings/notification/zen/ZenModeAddBypassingAppsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeAddBypassingAppsPreferenceController.java index e7529136d0c..5cffb9c5789 100644 --- a/src/com/android/settings/notification/zen/ZenModeAddBypassingAppsPreferenceController.java +++ b/src/com/android/settings/notification/zen/ZenModeAddBypassingAppsPreferenceController.java @@ -19,6 +19,7 @@ package com.android.settings.notification.zen; import android.app.Application; import android.app.settings.SettingsEnums; import android.content.Context; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.UserHandle; @@ -35,8 +36,10 @@ import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.SubSettingLauncher; import com.android.settings.notification.NotificationBackend; import com.android.settings.notification.app.AppChannelsBypassingDndSettings; +import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.widget.AppPreference; import java.util.ArrayList; @@ -120,6 +123,24 @@ public class ZenModeAddBypassingAppsPreferenceController extends AbstractPrefere updateAppList(apps); } + // Set the icon for the given preference to the entry icon from cache if available, or look + // it up. + private void updateIcon(Preference pref, ApplicationsState.AppEntry entry) { + synchronized (entry) { + final Drawable cachedIcon = AppUtils.getIconFromCache(entry); + if (cachedIcon != null && entry.mounted) { + pref.setIcon(cachedIcon); + } else { + ThreadUtils.postOnBackgroundThread(() -> { + final Drawable icon = AppUtils.getIcon(mPrefContext, entry); + if (icon != null) { + ThreadUtils.postOnMainThread(() -> pref.setIcon(icon)); + } + }); + } + } + } + @VisibleForTesting void updateAppList(List apps) { if (apps == null) { @@ -135,7 +156,6 @@ public class ZenModeAddBypassingAppsPreferenceController extends AbstractPrefere List appsWithNoBypassingDndNotificationChannels = new ArrayList<>(); for (ApplicationsState.AppEntry entry : apps) { String pkg = entry.info.packageName; - mApplicationsState.ensureIcon(entry); final int appChannels = mNotificationBackend.getChannelCount(pkg, entry.info.uid); final int appChannelsBypassingDnd = mNotificationBackend .getNotificationChannelsBypassingDnd(pkg, entry.info.uid).getList().size(); @@ -161,7 +181,7 @@ public class ZenModeAddBypassingAppsPreferenceController extends AbstractPrefere }); } pref.setTitle(BidiFormatter.getInstance().unicodeWrap(entry.label)); - pref.setIcon(entry.icon); + updateIcon(pref, entry); appsWithNoBypassingDndNotificationChannels.add(pref); } } diff --git a/src/com/android/settings/notification/zen/ZenModeAllBypassingAppsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeAllBypassingAppsPreferenceController.java index b036d8f55bc..4cbfacb31fc 100644 --- a/src/com/android/settings/notification/zen/ZenModeAllBypassingAppsPreferenceController.java +++ b/src/com/android/settings/notification/zen/ZenModeAllBypassingAppsPreferenceController.java @@ -19,6 +19,7 @@ package com.android.settings.notification.zen; import android.app.Application; import android.app.settings.SettingsEnums; import android.content.Context; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.UserHandle; @@ -35,8 +36,10 @@ import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.SubSettingLauncher; import com.android.settings.notification.NotificationBackend; import com.android.settings.notification.app.AppChannelsBypassingDndSettings; +import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.widget.AppPreference; import java.util.ArrayList; @@ -111,6 +114,24 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere updateAppList(apps); } + // Set the icon for the given preference to the entry icon from cache if available, or look + // it up. + private void updateIcon(Preference pref, ApplicationsState.AppEntry entry) { + synchronized (entry) { + final Drawable cachedIcon = AppUtils.getIconFromCache(entry); + if (cachedIcon != null && entry.mounted) { + pref.setIcon(cachedIcon); + } else { + ThreadUtils.postOnBackgroundThread(() -> { + final Drawable icon = AppUtils.getIcon(mPrefContext, entry); + if (icon != null) { + ThreadUtils.postOnMainThread(() -> pref.setIcon(icon)); + } + }); + } + } + } + @VisibleForTesting void updateAppList(List apps) { if (mPreferenceCategory == null || apps == null) { @@ -120,7 +141,6 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere List appsBypassingDnd = new ArrayList<>(); for (ApplicationsState.AppEntry app : apps) { String pkg = app.info.packageName; - mApplicationsState.ensureIcon(app); final int appChannels = mNotificationBackend.getChannelCount(pkg, app.info.uid); final int appChannelsBypassingDnd = mNotificationBackend .getNotificationChannelsBypassingDnd(pkg, app.info.uid).getList().size(); @@ -147,7 +167,7 @@ public class ZenModeAllBypassingAppsPreferenceController extends AbstractPrefere }); } pref.setTitle(BidiFormatter.getInstance().unicodeWrap(app.label)); - pref.setIcon(app.icon); + updateIcon(pref, app); if (appChannels > appChannelsBypassingDnd) { pref.setSummary(R.string.zen_mode_bypassing_apps_summary_some); } else { diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java index 45829f4500a..8614c53d4a6 100644 --- a/src/com/android/settings/users/UserSettings.java +++ b/src/com/android/settings/users/UserSettings.java @@ -528,6 +528,30 @@ public class UserSettings extends SettingsPreferenceFragment startActivity(intent); } + private void onAddGuestClicked() { + final UserCreatingDialog guestCreatingDialog = + new UserCreatingDialog(getActivity(), /* isGuest= */ true); + guestCreatingDialog.show(); + + ThreadUtils.postOnBackgroundThread(() -> { + mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_USER_GUEST_ADD); + Trace.beginSection("UserSettings.addGuest"); + final UserInfo guest = mUserManager.createGuest(getContext()); + Trace.endSection(); + + ThreadUtils.postOnMainThread(() -> { + guestCreatingDialog.dismiss(); + if (guest == null) { + Toast.makeText(getContext(), + com.android.settingslib.R.string.add_guest_failed, + Toast.LENGTH_SHORT).show(); + return; + } + openUserDetails(guest, true); + }); + }); + } + private void onRemoveUserClicked(int userId) { synchronized (mUserLock) { if (mRemovingUserId == -1 && !mAddingUser) { @@ -1283,17 +1307,7 @@ public class UserSettings extends SettingsPreferenceFragment return true; } else if (pref == mAddGuest) { mAddGuest.setEnabled(false); // prevent multiple tap issue - mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_USER_GUEST_ADD); - Trace.beginSection("UserSettings.addGuest"); - UserInfo guest = mUserManager.createGuest(getContext()); - Trace.endSection(); - if (guest == null) { - Toast.makeText(getContext(), - com.android.settingslib.R.string.add_user_failed, - Toast.LENGTH_SHORT).show(); - return true; - } - openUserDetails(guest, true); + onAddGuestClicked(); return true; } return false; diff --git a/src/com/android/settings/wifi/LongPressWifiEntryPreference.java b/src/com/android/settings/wifi/LongPressWifiEntryPreference.java index bee92cfbf8d..c509f1ab929 100644 --- a/src/com/android/settings/wifi/LongPressWifiEntryPreference.java +++ b/src/com/android/settings/wifi/LongPressWifiEntryPreference.java @@ -17,6 +17,7 @@ package com.android.settings.wifi; import android.content.Context; +import androidx.annotation.VisibleForTesting; import androidx.fragment.app.Fragment; import androidx.preference.PreferenceViewHolder; @@ -43,4 +44,23 @@ public class LongPressWifiEntryPreference extends WifiEntryPreference { view.itemView.setLongClickable(true); } } + + @Override + public void refresh() { + super.refresh(); + setEnabled(shouldEnabled()); + } + + @VisibleForTesting + boolean shouldEnabled() { + WifiEntry wifiEntry = getWifiEntry(); + if (wifiEntry == null) return false; + + boolean enabled = wifiEntry.canConnect(); + // If Wi-Fi is connected or saved network, leave it enabled to disconnect or configure. + if (!enabled && (wifiEntry.canDisconnect() || wifiEntry.isSaved())) { + enabled = true; + } + return enabled; + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest.java new file mode 100644 index 00000000000..89c91209ffd --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest.java @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.accessibility; + +import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_SAVED_QS_TOOLTIP_RESHOW; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.ComponentName; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.widget.LinearLayout; +import android.widget.PopupWindow; + +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.preference.PreferenceViewHolder; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.testutils.shadow.ShadowFragment; +import com.android.settingslib.PrimarySwitchPreference; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; +import org.robolectric.shadows.ShadowApplication; + +/** + * Tests for {@link AccessibilityQuickSettingsPrimarySwitchPreferenceController}. + */ +@RunWith(RobolectricTestRunner.class) +public class AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest { + + private static final String PLACEHOLDER_PACKAGE_NAME = "com.placeholder.example"; + private static final String PLACEHOLDER_TILE_CLASS_NAME = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder"; + private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName( + PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME); + private static final CharSequence PLACEHOLDER_TILE_CONTENT = + PLACEHOLDER_TILE_CLASS_NAME + ".tile.content"; + private static final String TEST_KEY = "test_pref_key"; + private static final String TEST_TITLE = "test_title"; + + @Rule + public final MockitoRule mockito = MockitoJUnit.rule(); + + @Spy + private final Context mContext = ApplicationProvider.getApplicationContext(); + + private TestAccessibilityQuickSettingsPrimarySwitchPreferenceController mController; + private PrimarySwitchPreference mPreference; + private TestFragment mFragment; + private PreferenceScreen mScreen; + private PreferenceViewHolder mHolder; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private PreferenceManager mPreferenceManager; + + private static PopupWindow getLatestPopupWindow() { + final ShadowApplication shadowApplication = + Shadow.extract(ApplicationProvider.getApplicationContext()); + return shadowApplication.getLatestPopupWindow(); + } + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext.setTheme(R.style.Theme_AppCompat); + mFragment = spy(new TestFragment()); + when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager); + when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext); + when(mFragment.getContext()).thenReturn(mContext); + mScreen = spy(new PreferenceScreen(mContext, /* attrs= */ null)); + when(mScreen.getPreferenceManager()).thenReturn(mPreferenceManager); + doReturn(mScreen).when(mFragment).getPreferenceScreen(); + + mPreference = new PrimarySwitchPreference(mContext); + mPreference.setKey(TEST_KEY); + mPreference.setTitle(TEST_TITLE); + LayoutInflater inflater = LayoutInflater.from(mContext); + mHolder = PreferenceViewHolder.createInstanceForTests(inflater.inflate( + com.android.settingslib.R.layout.preference_two_target, null)); + LinearLayout mWidgetView = mHolder.itemView.findViewById(android.R.id.widget_frame); + inflater.inflate(R.layout.preference_widget_primary_switch, mWidgetView, true); + mPreference.onBindViewHolder(mHolder); + + mController = new TestAccessibilityQuickSettingsPrimarySwitchPreferenceController(mContext, + TEST_KEY); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + mController.displayPreference(mScreen); + } + + @Test + public void setChecked_showTooltipView() { + mController.setChecked(true); + + assertThat(getLatestPopupWindow().isShowing()).isTrue(); + } + + @Test + public void setChecked_tooltipViewShown_notShowTooltipView() { + mController.setChecked(true); + getLatestPopupWindow().dismiss(); + mController.setChecked(false); + + mController.setChecked(true); + + assertThat(getLatestPopupWindow().isShowing()).isFalse(); + } + + @Test + @Config(shadows = ShadowFragment.class) + public void restoreValueFromSavedInstanceState_showTooltipView() { + mController.setChecked(true); + final Bundle savedInstanceState = new Bundle(); + savedInstanceState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true); + + mFragment.onCreate(savedInstanceState); + mController.displayPreference(mScreen); + + assertThat(getLatestPopupWindow().isShowing()).isTrue(); + } + + public static class TestAccessibilityQuickSettingsPrimarySwitchPreferenceController + extends AccessibilityQuickSettingsPrimarySwitchPreferenceController { + + public TestAccessibilityQuickSettingsPrimarySwitchPreferenceController(Context context, + String preferenceKey) { + super(context, preferenceKey); + } + + @Override + ComponentName getTileComponentName() { + return PLACEHOLDER_TILE_COMPONENT_NAME; + } + + @Override + CharSequence getTileTooltipContent() { + return PLACEHOLDER_TILE_CONTENT; + } + } + + private static class TestFragment extends SettingsPreferenceFragment { + + @Override + protected boolean shouldSkipForInitialSUW() { + return false; + } + + @Override + public int getMetricsCategory() { + return 0; + } + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java index d05600adad6..c7a5884d6e2 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java @@ -73,6 +73,8 @@ public class AccessibilityShortcutPreferenceFragmentTest { PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CLASS_NAME); private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName( PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME); + private static final String PLACEHOLDER_TILE_TOOLTIP_CONTENT = + PLACEHOLDER_PACKAGE_NAME + "tooltip_content"; private static final String PLACEHOLDER_DIALOG_TITLE = "title"; private static final String SOFTWARE_SHORTCUT_KEY = @@ -281,8 +283,8 @@ public class AccessibilityShortcutPreferenceFragmentTest { } @Override - protected CharSequence getTileName() { - return PLACEHOLDER_PACKAGE_NAME; + protected CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) { + return PLACEHOLDER_TILE_TOOLTIP_CONTENT; } @Override diff --git a/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java index c44352f6932..4660f77f275 100644 --- a/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java @@ -34,6 +34,9 @@ import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.R; +import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -44,8 +47,6 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.Shadows; import org.robolectric.shadows.ShadowPackageManager; -import java.util.Arrays; - /** Tests for {@link LaunchAccessibilityActivityPreferenceFragment} */ @RunWith(RobolectricTestRunner.class) public class LaunchAccessibilityActivityPreferenceFragmentTest { @@ -83,53 +84,91 @@ public class LaunchAccessibilityActivityPreferenceFragmentTest { } @Test - public void getTileName_noTileServiceAssigned_returnNull() { - assertThat(mFragment.getTileName()).isNull(); + public void getTileTooltipContent_noTileServiceAssigned_returnNull() { + final CharSequence tileTooltipContent = + mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT); + + assertThat(tileTooltipContent).isNull(); } @Test - public void getTileName_hasOneTileService_haveMatchString() { - final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE); - final ResolveInfo info = new ResolveInfo(); - info.serviceInfo = new FakeServiceInfo(); - info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; - info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME; - final ShadowPackageManager shadowPackageManager = - Shadows.shadowOf(mContext.getPackageManager()); - shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info)); + public void getTileTooltipContent_hasOneTileService_guideToEdit_haveMatchString() { + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME, + PLACEHOLDER_TILE_NAME); - final CharSequence tileName = mFragment.getTileName(); - assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME); + final CharSequence tileTooltipContent = + mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT); + final CharSequence tileName = + mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); + assertThat(tileTooltipContent.toString()).isEqualTo( + mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName)); } @Test - public void getTileName_hasTwoTileServices_haveMatchString() { + public void getTileTooltipContent_hasOneTileService_guideToDirectUse_haveMatchString() { + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME, + PLACEHOLDER_TILE_NAME); + + final CharSequence tileTooltipContent = + mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE); + final CharSequence tileName = + mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); + assertThat(tileTooltipContent.toString()).isEqualTo( + mContext.getString( + R.string.accessibility_service_auto_added_qs_tooltips_content, tileName)); + } + + @Test + public void getTileTooltipContent_hasTwoTileServices_guideToEdit_haveMatchString() { + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME, + PLACEHOLDER_TILE_NAME); + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME2, + PLACEHOLDER_TILE_NAME2); + + final CharSequence tileTooltipContent = + mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT); + final CharSequence tileName = + mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); + assertThat(tileTooltipContent.toString()).isEqualTo( + mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName)); + } + + @Test + public void getTileTooltipContent_hasTwoTileServices_guideToDirectUse_haveMatchString() { + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME, + PLACEHOLDER_TILE_NAME); + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME2, + PLACEHOLDER_TILE_NAME2); + + final CharSequence tileTooltipContent = + mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE); + final CharSequence tileName = + mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); + assertThat(tileTooltipContent.toString()).isEqualTo( + mContext.getString( + R.string.accessibility_service_auto_added_qs_tooltips_content, tileName)); + } + + private void setupTileService(String packageName, String name, String tileName) { final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE); final ResolveInfo info = new ResolveInfo(); - info.serviceInfo = new FakeServiceInfo(); - info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; - info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME; - final ResolveInfo info2 = new ResolveInfo(); - info2.serviceInfo = new FakeServiceInfo2(); - info2.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; - info2.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME2; + info.serviceInfo = new FakeServiceInfo(packageName, name, tileName); final ShadowPackageManager shadowPackageManager = Shadows.shadowOf(mContext.getPackageManager()); - shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info, info2)); - - final CharSequence tileName = mFragment.getTileName(); - assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME); + shadowPackageManager.addResolveInfoForIntent(tileProbe, info); } private static class FakeServiceInfo extends ServiceInfo { - public String loadLabel(PackageManager mgr) { - return PLACEHOLDER_TILE_NAME; - } - } + private String mTileName; + + FakeServiceInfo(String packageName, String name, String tileName) { + this.packageName = packageName; + this.name = name; + mTileName = tileName; + } - private static class FakeServiceInfo2 extends ServiceInfo { public String loadLabel(PackageManager mgr) { - return PLACEHOLDER_TILE_NAME2; + return mTileName; } } diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java index 236f9f2307c..ad5171ddaf5 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java @@ -34,6 +34,9 @@ import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.R; +import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -44,8 +47,6 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.Shadows; import org.robolectric.shadows.ShadowPackageManager; -import java.util.Arrays; - /** Tests for {@link ToggleAccessibilityServicePreferenceFragment} */ @RunWith(RobolectricTestRunner.class) public class ToggleAccessibilityServicePreferenceFragmentTest { @@ -83,53 +84,91 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test - public void getTileName_noTileServiceAssigned_returnNull() { - assertThat(mFragment.getTileName()).isNull(); + public void getTileTooltipContent_noTileServiceAssigned_returnNull() { + final CharSequence tileTooltipContent = + mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT); + + assertThat(tileTooltipContent).isNull(); } @Test - public void getTileName_hasOneTileService_haveMatchString() { - final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE); - final ResolveInfo info = new ResolveInfo(); - info.serviceInfo = new FakeServiceInfo(); - info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; - info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME; - final ShadowPackageManager shadowPackageManager = - Shadows.shadowOf(mContext.getPackageManager()); - shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info)); + public void getTileTooltipContent_hasOneTileService_guideToEdit_haveMatchString() { + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME, + PLACEHOLDER_TILE_NAME); - final CharSequence tileName = mFragment.getTileName(); - assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME); + final CharSequence tileTooltipContent = + mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT); + final CharSequence tileName = + mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); + assertThat(tileTooltipContent.toString()).isEqualTo( + mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName)); } @Test - public void getTileName_hasTwoTileServices_haveMatchString() { + public void getTileTooltipContent_hasOneTileService_guideToDirectUse_haveMatchString() { + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME, + PLACEHOLDER_TILE_NAME); + + final CharSequence tileTooltipContent = + mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE); + final CharSequence tileName = + mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); + assertThat(tileTooltipContent.toString()).isEqualTo( + mContext.getString( + R.string.accessibility_service_auto_added_qs_tooltips_content, tileName)); + } + + @Test + public void getTileTooltipContent_hasTwoTileServices_guideToEdit_haveMatchString() { + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME, + PLACEHOLDER_TILE_NAME); + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME2, + PLACEHOLDER_TILE_NAME2); + + final CharSequence tileTooltipContent = + mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT); + final CharSequence tileName = + mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); + assertThat(tileTooltipContent.toString()).isEqualTo( + mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName)); + } + + @Test + public void getTileTooltipContent_hasTwoTileServices_guideToDirectUse_haveMatchString() { + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME, + PLACEHOLDER_TILE_NAME); + setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME2, + PLACEHOLDER_TILE_NAME2); + + final CharSequence tileTooltipContent = + mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE); + final CharSequence tileName = + mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); + assertThat(tileTooltipContent.toString()).isEqualTo( + mContext.getString( + R.string.accessibility_service_auto_added_qs_tooltips_content, tileName)); + } + + private void setupTileService(String packageName, String name, String tileName) { final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE); final ResolveInfo info = new ResolveInfo(); - info.serviceInfo = new FakeServiceInfo(); - info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; - info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME; - final ResolveInfo info2 = new ResolveInfo(); - info2.serviceInfo = new FakeServiceInfo2(); - info2.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; - info2.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME2; + info.serviceInfo = new FakeServiceInfo(packageName, name, tileName); final ShadowPackageManager shadowPackageManager = Shadows.shadowOf(mContext.getPackageManager()); - shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info, info2)); - - final CharSequence tileName = mFragment.getTileName(); - assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME); + shadowPackageManager.addResolveInfoForIntent(tileProbe, info); } private static class FakeServiceInfo extends ServiceInfo { - public String loadLabel(PackageManager mgr) { - return PLACEHOLDER_TILE_NAME; - } - } + private String mTileName; + + FakeServiceInfo(String packageName, String name, String tileName) { + this.packageName = packageName; + this.name = name; + mTileName = tileName; + } - private static class FakeServiceInfo2 extends ServiceInfo { public String loadLabel(PackageManager mgr) { - return PLACEHOLDER_TILE_NAME2; + return mTileName; } } diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java index 34a2f5b3eba..04018a6b6d7 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java @@ -49,6 +49,7 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType; +import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType; import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; import com.android.settings.testutils.shadow.ShadowFragment; import com.android.settingslib.widget.TopIntroPreference; @@ -77,8 +78,8 @@ public class ToggleFeaturePreferenceFragmentTest { PLACEHOLDER_PACKAGE_NAME + "tile.placeholder"; private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName( PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME); - private static final String PLACEHOLDER_TILE_NAME = - PLACEHOLDER_PACKAGE_NAME + "tile.placeholder"; + private static final String PLACEHOLDER_TILE_TOOLTIP_CONTENT = + PLACEHOLDER_PACKAGE_NAME + "tooltip_content"; private static final String PLACEHOLDER_DIALOG_TITLE = "title"; private static final String DEFAULT_SUMMARY = "default summary"; private static final String DEFAULT_DESCRIPTION = "default description"; @@ -361,8 +362,8 @@ public class ToggleFeaturePreferenceFragmentTest { } @Override - CharSequence getTileName() { - return PLACEHOLDER_TILE_NAME; + protected CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) { + return PLACEHOLDER_TILE_TOOLTIP_CONTENT; } @Override diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java index d16a5079877..42b889cfa1a 100644 --- a/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java @@ -121,7 +121,7 @@ public class AbstractBluetoothDialogPreferenceControllerTest { @Test public void onIndexUpdated_checkFlow() { - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, null); + mCodecStatus = new BluetoothCodecStatus.Builder().setCodecConfig(mCodecConfigAAC).build(); when(mBluetoothA2dp.getCodecStatus( mActiveDevice)).thenReturn(mCodecStatus); when(mBluetoothA2dpConfigStore.createCodecConfig()).thenReturn(mCodecConfigAAC); @@ -161,7 +161,7 @@ public class AbstractBluetoothDialogPreferenceControllerTest { @Test public void getCurrentCodecConfig_verifyConfig() { - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, null); + mCodecStatus = new BluetoothCodecStatus.Builder().setCodecConfig(mCodecConfigAAC).build(); when(mBluetoothA2dp.getCodecStatus( mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); @@ -171,8 +171,10 @@ public class AbstractBluetoothDialogPreferenceControllerTest { @Test public void getSelectableConfigs_verifyConfig() { - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus( mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); @@ -182,8 +184,10 @@ public class AbstractBluetoothDialogPreferenceControllerTest { @Test public void getSelectableByCodecType_verifyConfig() { - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus( mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); @@ -194,8 +198,10 @@ public class AbstractBluetoothDialogPreferenceControllerTest { @Test public void getSelectableByCodecType_unavailable() { - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus( mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); @@ -206,8 +212,10 @@ public class AbstractBluetoothDialogPreferenceControllerTest { @Test public void onBluetoothServiceConnected_verifyBluetoothA2dpConfigStore() { - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus( mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java index 5a24c8e5adf..dba1fbfe610 100644 --- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java @@ -102,8 +102,10 @@ public class BluetoothBitPerSampleDialogPreferenceControllerTest { @Test public void writeConfigurationValues_selectDefault_setHighest() { BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC}; - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); @@ -132,8 +134,10 @@ public class BluetoothBitPerSampleDialogPreferenceControllerTest { @Test public void getSelectableIndex_verifyList() { BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC}; - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); List indexList = new ArrayList<>(); diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java index 3d94e2a30d7..570257a91bd 100644 --- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java @@ -102,8 +102,10 @@ public class BluetoothChannelModeDialogPreferenceControllerTest { @Test public void writeConfigurationValues_selectDefault_setHighest() { BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC}; - mCodecStatus = new BluetoothCodecStatus(mCodecConfigSBC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigSBC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); @@ -129,8 +131,10 @@ public class BluetoothChannelModeDialogPreferenceControllerTest { @Test public void getSelectableIndex_verifyList() { BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC}; - mCodecStatus = new BluetoothCodecStatus(mCodecConfigSBC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigSBC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); List indexList = new ArrayList<>(); diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java index 21111cd028e..f04a80d1988 100644 --- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java @@ -126,8 +126,10 @@ public class BluetoothCodecDialogPreferenceControllerTest { @Test public void writeConfigurationValues_selectDefault_setHighest() { BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC}; - mCodecStatus = new BluetoothCodecStatus(mCodecConfigSBC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigSBC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus); when(mBluetoothA2dp.isOptionalCodecsEnabled(mActiveDevice)).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED); @@ -141,8 +143,10 @@ public class BluetoothCodecDialogPreferenceControllerTest { public void writeConfigurationValues_checkCodec() { BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC, mCodecConfigAPTX, mCodecConfigAPTXHD, mCodecConfigLDAC, mCodecConfigAAC, mCodecConfigSBC}; - mCodecStatus = new BluetoothCodecStatus(mCodecConfigSBC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigSBC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); @@ -169,8 +173,10 @@ public class BluetoothCodecDialogPreferenceControllerTest { public void writeConfigurationValues_resetHighestConfig() { BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC, mCodecConfigAPTX, mCodecConfigAPTXHD, mCodecConfigLDAC, mCodecConfigAAC, mCodecConfigSBC}; - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); mController.writeConfigurationValues(2); @@ -201,9 +207,10 @@ public class BluetoothCodecDialogPreferenceControllerTest { @Test public void onHDAudioEnabled_optionalCodecEnabled_setsCodecTypeAsAAC() { List mCodecConfigs = Arrays.asList(mCodecConfigAAC, mCodecConfigSBC); - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, - /* codecsLocalCapabilities= */ null, - mCodecConfigs); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(mCodecConfigs) + .build(); when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus); when(mBluetoothA2dp.isOptionalCodecsEnabled(mActiveDevice)).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED); @@ -217,9 +224,10 @@ public class BluetoothCodecDialogPreferenceControllerTest { @Test public void onHDAudioEnabled_optionalCodecDisabled_setsCodecTypeAsSBC() { List mCodecConfigs = Arrays.asList(mCodecConfigAAC, mCodecConfigSBC); - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, - /* codecsLocalCapabilities= */ null, - mCodecConfigs); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(mCodecConfigs) + .build(); when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus); when(mBluetoothA2dp.isOptionalCodecsEnabled(mActiveDevice)).thenReturn( BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED); diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java index 1bd83f7954d..359d24ede82 100644 --- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java @@ -122,8 +122,10 @@ public class BluetoothQualityDialogPreferenceControllerTest { @Test public void updateState_codeTypeIsLDAC_enablePreference() { BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigLDAC}; - mCodecStatus = new BluetoothCodecStatus(mCodecConfigLDAC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigLDAC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); mController.updateState(mPreference); @@ -134,8 +136,10 @@ public class BluetoothQualityDialogPreferenceControllerTest { @Test public void updateState_codeTypeAAC_disablePreference() { BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigLDAC}; - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); mController.updateState(mPreference); diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java index f7d010cb53b..fa4a79c293e 100644 --- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java @@ -106,8 +106,10 @@ public class BluetoothSampleRateDialogPreferenceControllerTest { .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC) .build(); BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC}; - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, - Arrays.asList(mCodecConfigs)); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs)) + .build(); when(mBluetoothA2dp.getCodecStatus( mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); @@ -143,7 +145,10 @@ public class BluetoothSampleRateDialogPreferenceControllerTest { add(mCodecConfigAAC); add(mCodecConfigSBC); }}; - mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, mCodecConfigs); + mCodecStatus = new BluetoothCodecStatus.Builder() + .setCodecConfig(mCodecConfigAAC) + .setCodecsSelectableCapabilities(mCodecConfigs) + .build(); when(mBluetoothA2dp.getCodecStatus( mActiveDevice)).thenReturn(mCodecStatus); mController.onBluetoothServiceConnected(mBluetoothA2dp); diff --git a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java index 28a071aca02..d364a3be451 100644 --- a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java @@ -21,6 +21,9 @@ import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_ import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.verify; + +import android.app.settings.SettingsEnums; import android.content.Context; import androidx.preference.Preference; @@ -30,11 +33,15 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; import com.android.settings.testutils.shadow.ShadowRotationPolicy; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; import com.android.settingslib.search.SearchIndexableRaw; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @@ -54,12 +61,26 @@ public class DeviceStateAutoRotateSettingControllerTest { private static final int DEFAULT_ORDER = -10; private final Context mContext = RuntimeEnvironment.application; - private final DeviceStateAutoRotateSettingController mController = - new DeviceStateAutoRotateSettingController(mContext, DEFAULT_DEVICE_STATE, - DEFAULT_DEVICE_STATE_DESCRIPTION, DEFAULT_ORDER); private final DeviceStateRotationLockSettingsManager mAutoRotateSettingsManager = DeviceStateRotationLockSettingsManager.getInstance(mContext); + @Mock private MetricsFeatureProvider mMetricsFeatureProvider; + + private DeviceStateAutoRotateSettingController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mController = new DeviceStateAutoRotateSettingController( + mContext, + DEFAULT_DEVICE_STATE, + DEFAULT_DEVICE_STATE_DESCRIPTION, + DEFAULT_ORDER, + mMetricsFeatureProvider + ); + } + @Test public void displayPreference_addsPreferenceToPreferenceScreen() { PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext); @@ -143,6 +164,22 @@ public class DeviceStateAutoRotateSettingControllerTest { assertThat(rotationLocked).isTrue(); } + @Test + public void setChecked_true_logsDeviceStateBasedSettingOn() { + mController.setChecked(true); + + verify(mMetricsFeatureProvider).action(mContext, + SettingsEnums.ACTION_ENABLE_AUTO_ROTATION_DEVICE_STATE, DEFAULT_DEVICE_STATE); + } + + @Test + public void setChecked_false_logsDeviceStateBasedSettingOff() { + mController.setChecked(false); + + verify(mMetricsFeatureProvider).action(mContext, + SettingsEnums.ACTION_DISABLE_AUTO_ROTATION_DEVICE_STATE, DEFAULT_DEVICE_STATE); + } + @Test public void updateRawDataToIndex_addsItemToList() { List rawData = new ArrayList<>(); diff --git a/tests/robotests/src/com/android/settings/dream/DreamMainSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/dream/DreamMainSwitchPreferenceControllerTest.java new file mode 100644 index 00000000000..fb55164b073 --- /dev/null +++ b/tests/robotests/src/com/android/settings/dream/DreamMainSwitchPreferenceControllerTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.dream; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.provider.Settings; + +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settingslib.dream.DreamBackend; +import com.android.settingslib.widget.MainSwitchPreference; +import com.android.settingslib.widget.OnMainSwitchChangeListener; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; +import org.robolectric.shadows.ShadowContentResolver; +import org.robolectric.shadows.ShadowSettings; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowSettings.ShadowSecure.class}) +public class DreamMainSwitchPreferenceControllerTest { + + private Context mContext; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private PreferenceScreen mScreen; + private DreamMainSwitchPreferenceController mController; + private MainSwitchPreference mPreference; + private DreamBackend mBackend; + @Mock + private OnMainSwitchChangeListener mChangeListener; + private ShadowContentResolver mShadowContentResolver; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = ApplicationProvider.getApplicationContext(); + mShadowContentResolver = Shadow.extract(mContext.getContentResolver()); + mBackend = DreamBackend.getInstance(mContext); + mController = new DreamMainSwitchPreferenceController(mContext, "key"); + mPreference = new MainSwitchPreference(mContext); + mPreference.setKey(mController.getPreferenceKey()); + when(mScreen.findPreference(mPreference.getKey())).thenReturn(mPreference); + mController.displayPreference(mScreen); + } + + @After + public void tearDown() { + ShadowSettings.ShadowSecure.reset(); + mController.onStop(); + } + + @Test + public void testIsChecked_returnsFalse() { + mBackend.setEnabled(false); + assertThat(mController.isChecked()).isFalse(); + } + + @Test + public void testIsChecked_returnsTrue() { + mBackend.setEnabled(true); + assertThat(mController.isChecked()).isTrue(); + } + + @Test + public void testSetChecked_setFalse_disablesSetting() { + mBackend.setEnabled(true); + mController.setChecked(false); + assertThat(mBackend.isEnabled()).isFalse(); + } + + @Test + public void testSetChecked_setTrue_enablesSetting() { + mBackend.setEnabled(false); + mController.setChecked(true); + assertThat(mBackend.isEnabled()).isTrue(); + } + + @Test + public void testIsSliceable_returnsFalse() { + assertThat(mController.isSliceable()).isFalse(); + } + + @Test + public void testRegisterAndUnregister() { + mController.onStart(); + assertThat(mShadowContentResolver.getContentObservers( + Settings.Secure.getUriFor(Settings.Secure.SCREENSAVER_ENABLED))).hasSize(1); + + mController.onStop(); + assertThat(mShadowContentResolver.getContentObservers( + Settings.Secure.getUriFor(Settings.Secure.SCREENSAVER_ENABLED))).isEmpty(); + } + + @Test + public void testUpdateState() { + mController.onStart(); + + mBackend.setEnabled(true); + triggerOnChangeListener(); + assertThat(mPreference.isChecked()).isTrue(); + + mBackend.setEnabled(false); + triggerOnChangeListener(); + assertThat(mPreference.isChecked()).isFalse(); + + mBackend.setEnabled(true); + triggerOnChangeListener(); + assertThat(mPreference.isChecked()).isTrue(); + } + + private void triggerOnChangeListener() { + mShadowContentResolver.getContentObservers( + Settings.Secure.getUriFor(Settings.Secure.SCREENSAVER_ENABLED)) + .forEach(contentObserver -> contentObserver.onChange(false)); + } +} diff --git a/tests/robotests/src/com/android/settings/dream/DreamPickerControllerTest.java b/tests/robotests/src/com/android/settings/dream/DreamPickerControllerTest.java index 401ffe0700f..7a5299f35e3 100644 --- a/tests/robotests/src/com/android/settings/dream/DreamPickerControllerTest.java +++ b/tests/robotests/src/com/android/settings/dream/DreamPickerControllerTest.java @@ -62,7 +62,8 @@ public class DreamPickerControllerTest { } private DreamPickerController buildController() { - final DreamPickerController controller = new DreamPickerController(mContext, mBackend); + final DreamPickerController controller = new DreamPickerController(mContext, "key", + mBackend); controller.displayPreference(mScreen); return controller; } diff --git a/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java b/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java index fd0cf5fc264..16f8599f2f1 100644 --- a/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java +++ b/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java @@ -18,18 +18,19 @@ package com.android.settings.dream; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.Activity; import android.content.Context; import android.os.UserManager; +import androidx.test.core.app.ApplicationProvider; + import com.android.settings.testutils.FakeFeatureFactory; import com.android.settingslib.dream.DreamBackend; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; @@ -39,25 +40,24 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.util.ReflectionHelpers; @RunWith(RobolectricTestRunner.class) -@Ignore public class WhenToDreamPickerTest { private WhenToDreamPicker mPicker; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private DreamBackend mBackend; - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private Activity mActivity; @Mock private UserManager mUserManager; @Before public void setup() { MockitoAnnotations.initMocks(this); - when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); + final Context context = spy(ApplicationProvider.getApplicationContext()); + + when(context.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); FakeFeatureFactory.setupForTest(); mPicker = new WhenToDreamPicker(); - mPicker.onAttach((Context) mActivity); + mPicker.onAttach(context); ReflectionHelpers.setField(mPicker, "mBackend", mBackend); } diff --git a/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsFragmentTest.java index b014076ed57..e85f713af4c 100644 --- a/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsFragmentTest.java +++ b/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsFragmentTest.java @@ -43,19 +43,21 @@ public class ButtonNavigationSettingsFragmentTest { } @Test - public void getNonIndexableKeys_twoButtonNavigationAvailable_allKeysIndexable() { + public void getNonIndexableKeys_twoButtonNavigationAvailable_allKeysExceptAnimIndexable() { addPackageToPackageManager(ApplicationProvider.getApplicationContext(), NAV_BAR_MODE_2BUTTON_OVERLAY); assertThat(ButtonNavigationSettingsFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys( - ApplicationProvider.getApplicationContext())).isEmpty(); + ApplicationProvider.getApplicationContext())).containsExactly( + "gesture_power_menu_video"); } @Test - public void getNonIndexableKeys_threeButtonNavigationAvailable_allKeysIndexable() { + public void getNonIndexableKeys_threeButtonNavigationAvailable_allKeysExceptAnimIndexable() { addPackageToPackageManager(ApplicationProvider.getApplicationContext(), NAV_BAR_MODE_3BUTTON_OVERLAY); assertThat(ButtonNavigationSettingsFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys( - ApplicationProvider.getApplicationContext())).isEmpty(); + ApplicationProvider.getApplicationContext())).containsExactly( + "gesture_power_menu_video"); } private static void addPackageToPackageManager(Context context, String pkg) { diff --git a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java index 999487659cb..3182cd0db41 100644 --- a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java +++ b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java @@ -108,6 +108,8 @@ public class NetworkProviderSettingsTest { @Mock private WifiPickerTracker mMockWifiPickerTracker; @Mock + private WifiEntry mWifiEntry; + @Mock private PreferenceManager mPreferenceManager; @Mock private InternetResetHelper mInternetResetHelper; @@ -309,14 +311,13 @@ public class NetworkProviderSettingsTest { when(activity.getApplicationContext()).thenReturn(mContext); when(mNetworkProviderSettings.getActivity()).thenReturn(activity); - final WifiEntry wifiEntry = mock(WifiEntry.class); - when(wifiEntry.canDisconnect()).thenReturn(true); - when(wifiEntry.canForget()).thenReturn(true); - when(wifiEntry.isSaved()).thenReturn(true); - when(wifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED); + when(mWifiEntry.canDisconnect()).thenReturn(true); + when(mWifiEntry.canForget()).thenReturn(true); + when(mWifiEntry.isSaved()).thenReturn(true); + when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED); final LongPressWifiEntryPreference connectedWifiEntryPreference = - mNetworkProviderSettings.createLongPressWifiEntryPreference(wifiEntry); + mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry); final View view = mock(View.class); when(view.getTag()).thenReturn(connectedWifiEntryPreference); @@ -334,15 +335,14 @@ public class NetworkProviderSettingsTest { when(activity.getApplicationContext()).thenReturn(mContext); when(mNetworkProviderSettings.getActivity()).thenReturn(activity); - final WifiEntry wifiEntry = mock(WifiEntry.class); - when(wifiEntry.canDisconnect()).thenReturn(true); - when(wifiEntry.canShare()).thenReturn(true); - when(wifiEntry.canForget()).thenReturn(true); - when(wifiEntry.isSaved()).thenReturn(true); - when(wifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED); + when(mWifiEntry.canDisconnect()).thenReturn(true); + when(mWifiEntry.canShare()).thenReturn(true); + when(mWifiEntry.canForget()).thenReturn(true); + when(mWifiEntry.isSaved()).thenReturn(true); + when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED); final LongPressWifiEntryPreference connectedWifiEntryPreference = - mNetworkProviderSettings.createLongPressWifiEntryPreference(wifiEntry); + mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry); final View view = mock(View.class); when(view.getTag()).thenReturn(connectedWifiEntryPreference); @@ -358,15 +358,14 @@ public class NetworkProviderSettingsTest { when(activity.getApplicationContext()).thenReturn(mContext); when(mNetworkProviderSettings.getActivity()).thenReturn(activity); - final WifiEntry wifiEntry = mock(WifiEntry.class); - when(wifiEntry.canDisconnect()).thenReturn(true); - when(wifiEntry.canShare()).thenReturn(false); - when(wifiEntry.canForget()).thenReturn(true); - when(wifiEntry.isSaved()).thenReturn(true); - when(wifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED); + when(mWifiEntry.canDisconnect()).thenReturn(true); + when(mWifiEntry.canShare()).thenReturn(false); + when(mWifiEntry.canForget()).thenReturn(true); + when(mWifiEntry.isSaved()).thenReturn(true); + when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED); final LongPressWifiEntryPreference connectedWifiEntryPreference = - mNetworkProviderSettings.createLongPressWifiEntryPreference(wifiEntry); + mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry); final View view = mock(View.class); when(view.getTag()).thenReturn(connectedWifiEntryPreference); @@ -390,10 +389,9 @@ public class NetworkProviderSettingsTest { FAKE_URI_STRING); doNothing().when(mNetworkProviderSettings).startActivityForResult(any(Intent.class), anyInt()); - final WifiEntry mockWifiEntry = mock(WifiEntry.class); - when(mockWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING); + when(mWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING); - mNetworkProviderSettings.openSubscriptionHelpPage(mockWifiEntry); + mNetworkProviderSettings.openSubscriptionHelpPage(mWifiEntry); verify(mNetworkProviderSettings, times(1)).startActivityForResult(any(), anyInt()); } @@ -461,12 +459,11 @@ public class NetworkProviderSettingsTest { } private WifiDialog2 createWifiDialog2(int mode, WifiConfiguration config) { - final WifiEntry wifiEntry = mock(WifiEntry.class); - when(wifiEntry.canConnect()).thenReturn(true); + when(mWifiEntry.canConnect()).thenReturn(true); final WifiConfigController2 controller = mock(WifiConfigController2.class); when(controller.getConfig()).thenReturn(config); - final WifiDialog2 wifiDialog2 = spy(WifiDialog2.createModal(mContext, null /* listener */, - wifiEntry, mode)); + final WifiDialog2 wifiDialog2 = spy(WifiDialog2.createModal(mContext, null /* listener */, + mWifiEntry, mode)); when(wifiDialog2.getController()).thenReturn(controller); return wifiDialog2; } @@ -537,20 +534,18 @@ public class NetworkProviderSettingsTest { @Test public void createConnectedWifiEntryPreference_internetWiFi_createConnectedPreference() { - final WifiEntry wifiEntry = mock(WifiEntry.class); doReturn(InternetUpdater.INTERNET_WIFI).when(mInternetUpdater).getInternetType(); - final Preference p = mNetworkProviderSettings.createConnectedWifiEntryPreference(wifiEntry); + Preference p = mNetworkProviderSettings.createConnectedWifiEntryPreference(mWifiEntry); assertThat(p instanceof ConnectedWifiEntryPreference).isTrue(); } @Test public void createConnectedWifiEntryPreference_internetCellular_createFirstWifiPreference() { - final WifiEntry wifiEntry = mock(WifiEntry.class); doReturn(InternetUpdater.INTERNET_CELLULAR).when(mInternetUpdater).getInternetType(); - final Preference p = mNetworkProviderSettings.createConnectedWifiEntryPreference(wifiEntry); + Preference p = mNetworkProviderSettings.createConnectedWifiEntryPreference(mWifiEntry); assertThat(p instanceof NetworkProviderSettings.FirstWifiEntryPreference).isTrue(); } @@ -634,6 +629,42 @@ public class NetworkProviderSettingsTest { assertThat(mNetworkProviderSettings.mWifiStatusMessagePreference.isVisible()).isFalse(); } + @Test + public void onSelectedWifiPreferenceClick_shouldEditBeforeConnect_launchNewNetworkFragment() { + when(mWifiEntry.shouldEditBeforeConnect()).thenReturn(true); + final LongPressWifiEntryPreference preference = + mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry); + doNothing().when(mNetworkProviderSettings).launchConfigNewNetworkFragment(mWifiEntry); + + mNetworkProviderSettings.onSelectedWifiPreferenceClick(preference); + + verify(mNetworkProviderSettings).launchConfigNewNetworkFragment(mWifiEntry); + } + + @Test + public void onSelectedWifiPreferenceClick_canConnect_connectWifi() { + when(mWifiEntry.canConnect()).thenReturn(true); + final LongPressWifiEntryPreference preference = + mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry); + doNothing().when(mNetworkProviderSettings).connect(any(), anyBoolean(), anyBoolean()); + + mNetworkProviderSettings.onSelectedWifiPreferenceClick(preference); + + verify(mNetworkProviderSettings).connect(any(), anyBoolean(), anyBoolean()); + } + + @Test + public void onSelectedWifiPreferenceClick_isSaved_launchNetworkDetailsFragment() { + when(mWifiEntry.isSaved()).thenReturn(true); + final LongPressWifiEntryPreference preference = + mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry); + doNothing().when(mNetworkProviderSettings).launchNetworkDetailsFragment(preference); + + mNetworkProviderSettings.onSelectedWifiPreferenceClick(preference); + + verify(mNetworkProviderSettings).launchNetworkDetailsFragment(preference); + } + @Test @Config(shadows = ShadowPreferenceFragmentCompat.class) public void onStop_shouldRemoveCallbacks() { diff --git a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java index e31d959622a..057b6cbf0b9 100644 --- a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java @@ -26,6 +26,7 @@ import static androidx.lifecycle.Lifecycle.Event.ON_START; import static androidx.lifecycle.Lifecycle.Event.ON_STOP; import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER; import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; import static com.google.common.truth.Truth.assertThat; @@ -35,6 +36,7 @@ import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; @@ -109,6 +111,8 @@ public class PrivateDnsPreferenceControllerTest { private Network mNetwork; @Mock private Preference mPreference; + @Mock + private UserManager mUserManager; @Captor private ArgumentCaptor mCallbackCaptor; private PrivateDnsPreferenceController mController; @@ -127,6 +131,7 @@ public class PrivateDnsPreferenceControllerTest { mShadowContentResolver = Shadow.extract(mContentResolver); when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)) .thenReturn(mConnectivityManager); + when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); doNothing().when(mConnectivityManager).registerDefaultNetworkCallback( mCallbackCaptor.capture(), nullable(Handler.class)); @@ -173,6 +178,12 @@ public class PrivateDnsPreferenceControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); } + @Test + public void getAvailabilityStatus_disabledForGuestUser() { + doReturn(true).when(mUserManager).isGuestUser(); + assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER); + } + @Test public void goThroughLifecycle_shouldRegisterUnregisterSettingsObserver() { mLifecycle.handleLifecycleEvent(ON_START); diff --git a/tests/robotests/src/com/android/settings/wifi/LongPressWifiEntryPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/LongPressWifiEntryPreferenceTest.java new file mode 100644 index 00000000000..fd7cc8943c9 --- /dev/null +++ b/tests/robotests/src/com/android/settings/wifi/LongPressWifiEntryPreferenceTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.wifi; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import android.content.Context; + +import androidx.fragment.app.Fragment; +import androidx.test.core.app.ApplicationProvider; + +import com.android.wifitrackerlib.WifiEntry; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class LongPressWifiEntryPreferenceTest { + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Spy + Context mContext = ApplicationProvider.getApplicationContext(); + @Mock + Fragment mFragment; + @Mock + WifiEntry mWifiEntry; + + LongPressWifiEntryPreference mPreference; + + @Before + public void setUp() { + // Fake mWifiEntry as an available Wi-Fi network, and it's not connected. + when(mWifiEntry.canConnect()).thenReturn(true); + when(mWifiEntry.canDisconnect()).thenReturn(false); + when(mWifiEntry.isSaved()).thenReturn(false); + + mPreference = new LongPressWifiEntryPreference(mContext, mWifiEntry, mFragment); + } + + @Test + public void shouldEnabled_canConnect_returnTrue() { + // Fake mWifiEntry as an available Wi-Fi network, and it's not connected. + when(mWifiEntry.canConnect()).thenReturn(true); + + assertThat(mPreference.shouldEnabled()).isTrue(); + } + + @Test + public void shouldEnabled_canNotConnect_returnFalse() { + // Fake mWifiEntry as a restricted Wi-Fi network, and cannot connect. + when(mWifiEntry.canConnect()).thenReturn(false); + + assertThat(mPreference.shouldEnabled()).isFalse(); + } + + @Test + public void shouldEnabled_canNotConnectButCanDisconnect_returnTrue() { + // Fake mWifiEntry as a connected Wi-Fi network without saved configuration. + when(mWifiEntry.canConnect()).thenReturn(false); + when(mWifiEntry.canDisconnect()).thenReturn(true); + + assertThat(mPreference.shouldEnabled()).isTrue(); + } + + @Test + public void shouldEnabled_canNotConnectButIsSaved_returnTrue() { + // Fake mWifiEntry as a saved Wi-Fi network + when(mWifiEntry.canConnect()).thenReturn(false); + when(mWifiEntry.isSaved()).thenReturn(true); + + assertThat(mPreference.shouldEnabled()).isTrue(); + } + + @Test + public void shouldEnabled_canNotConnectButCanDisconnectAndIsSaved_returnTrue() { + // Fake mWifiEntry as a connected Wi-Fi network + when(mWifiEntry.canConnect()).thenReturn(false); + when(mWifiEntry.canDisconnect()).thenReturn(true); + when(mWifiEntry.isSaved()).thenReturn(true); + + assertThat(mPreference.shouldEnabled()).isTrue(); + } +}