Merge "Use isEssentialPackage instead of isSystemPackage"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8abdb09..132fc29 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -847,6 +847,37 @@
</activity>
<activity
+ android:name="Settings$LongBackgroundTasksActivity"
+ android:exported="true"
+ android:label="@string/long_background_tasks_label">
+ <intent-filter android:priority="1">
+ <action android:name="android.settings.MANAGE_APP_LONG_JOBS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.applications.manageapplications.ManageApplications" />
+ <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+ android:value="@string/menu_key_apps"/>
+ <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+ android:value="true" />
+ </activity>
+
+ <activity
+ android:name="Settings$LongBackgroundTasksAppActivity"
+ android:exported="true"
+ android:label="@string/long_background_tasks_label">
+ <intent-filter android:priority="1">
+ <action android:name="android.settings.MANAGE_APP_LONG_JOBS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="package" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.applications.appinfo.LongBackgroundTasksDetails" />
+ <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+ android:value="@string/menu_key_apps"/>
+ </activity>
+
+ <activity
android:name="Settings$DateTimeSettingsActivity"
android:label="@string/date_and_time"
android:exported="true"
diff --git a/res/raw/udfps_center_hint_lottie.json b/res/raw/udfps_center_hint_lottie.json
new file mode 100644
index 0000000..c92e28d
--- /dev/null
+++ b/res/raw/udfps_center_hint_lottie.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":211,"w":412,"h":200,"nm":"FPS Pad","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue200","cl":"blue200","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":55,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":85,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":110,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":115,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":140,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":165,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":170,"s":[100]},{"t":195,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[176.139,66.987,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.408,-0.232],[1.017,0.68],[-0.959,1.434],[-6.841,3.896],[-7.562,0.41],[-0.093,-1.722],[1.724,-0.094],[6.003,-3.419],[3.674,-5.493]],"o":[[-0.995,0.567],[-1.433,-0.959],[4.21,-6.294],[6.841,-3.896],[1.722,-0.093],[0.094,1.722],[-6.599,0.357],[-6.003,3.418],[-0.279,0.417]],"v":[[-16.693,13.1],[-19.976,12.983],[-20.836,8.652],[-3.944,-6.925],[18.072,-13.506],[21.359,-10.556],[18.409,-7.27],[-0.853,-1.498],[-15.645,12.124]],"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":[[7.044,-4.012],[6.96,0.908],[-0.223,1.71],[-1.711,-0.224],[-5.298,3.017],[-2.065,5.824],[-1.624,-0.577],[0.576,-1.626]],"o":[[-6.489,3.695],[-1.71,-0.223],[0.223,-1.71],[5.601,0.73],[5.742,-3.27],[0.577,-1.625],[1.625,0.576],[-2.566,7.236]],"v":[[44.597,78.169],[24.039,82.43],[21.346,78.93],[24.846,76.237],[41.507,72.742],[53.614,58.64],[57.601,56.74],[59.5,60.727]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0.323,-0.184],[1.029,0.844],[0.13,0.229],[-15.469,8.81],[-8.28,-14.539],[1.498,-0.853],[0.853,1.498],[12.426,-7.076],[-6.547,-11.496],[-4.085,-3.35],[1.094,-1.333]],"o":[[-1.091,0.621],[-5.004,-4.103],[-8.28,-14.539],[15.469,-8.81],[0.853,1.498],[-1.498,0.853],[-6.547,-11.496],[-12.426,7.077],[0.024,0.042],[1.333,1.093],[-0.25,0.305]],"v":[[10.147,71.146],[6.621,70.847],[-1.636,61.086],[11.185,19.448],[53.537,29.665],[52.369,33.924],[48.111,32.756],[14.276,24.874],[3.791,57.996],[10.581,66.018],[11.016,70.413]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[1.183,-0.674],[0.287,-0.071],[3.505,8.779],[-6.102,3.475],[-3.887,-4.766],[0,0],[-3.067,1.747],[1.97,3.459],[0,0],[-1.498,0.853],[-0.853,-1.498],[0,0],[6.451,-3.674],[4.175,5.108],[0,0],[2.675,-1.523],[-1.489,-3.73],[-5.283,1.305],[-0.414,-1.674]],"o":[[-0.244,0.139],[-9.188,2.268],[-2.649,-6.633],[5.335,-3.038],[0,0],[2.235,2.735],[3.459,-1.97],[0,0],[-0.853,-1.498],[1.498,-0.853],[0,0],[3.674,6.452],[-5.725,3.26],[0,0],[-1.949,-2.391],[-3.377,1.923],[2.674,6.697],[1.674,-0.413],[0.342,1.387]],"v":[[36.276,64.961],[35.477,65.279],[11.151,49.991],[16.667,33.848],[32.582,36.831],[36.686,41.876],[45.842,43.586],[48.542,33.739],[47.994,32.777],[49.163,28.518],[53.421,29.686],[53.969,30.648],[48.932,49.012],[31.846,45.823],[27.739,40.774],[19.758,39.275],[16.951,47.675],[33.98,59.216],[37.761,61.499]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0.501,-0.285],[0.978,0.515],[11.066,-6.302],[0.514,-9.958],[1.721,0.088],[-0.089,1.722],[-13.068,7.442],[-10.828,-5.692],[0.802,-1.526]],"o":[[-0.895,0.51],[-8.827,-4.639],[-11.066,6.302],[-0.089,1.722],[-1.722,-0.089],[0.63,-12.217],[13.068,-7.442],[1.527,0.802],[-0.288,0.548]],"v":[[42.238,8.912],[39.237,8.964],[6.49,11.701],[-12.571,38.468],[-15.851,41.426],[-18.808,38.146],[3.4,6.274],[42.142,3.436],[43.453,7.653]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.682352941176,0.796078431373,0.980392156863,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":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":960,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Fingerprint Side","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[169.175,161.377,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],[0,0]],"o":[[7.894,8.852],[0,0]],"v":[[-7.497,-6.019],[7.497,6.019]],"c":false},"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],[-13.066,-25.141],[-1.414,-2.132]],"o":[[0,0],[1.326,2.55],[0,0]],"v":[[-25.707,-58.269],[-17.526,-20.998],[-13.399,-13.981]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[-10.063,-10.595],[0,0]],"o":[[0.312,1.13],[11.84,12.467],[0,0]],"v":[[-8.095,-38.352],[4.748,-14.866],[28.345,-2.398]],"c":false},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[3.585,11.306],[0,0]],"v":[[90.35,-61.769],[93.054,-42.731]],"c":false},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0,0],[-14.956,-24.065],[-1.112,-2.304]],"o":[[0,0],[1.517,2.441],[0,0]],"v":[[54.72,-104.215],[82.601,-78.164],[86.53,-71.035]],"c":false},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[0,0],[-3.978,-14.061],[0,0]],"o":[[0.813,0.844],[4.681,16.544],[0,0]],"v":[[63.033,-78.092],[76.68,-55.064],[75.364,-28.408]],"c":false},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.596069335938,0.321563720703,0.239196777344,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"ix":5},"lc":2,"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":"Group 1","np":7,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":960,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Fingerprint","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[176.139,66.987,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.408,-0.232],[1.017,0.68],[-0.959,1.434],[-6.841,3.896],[-7.562,0.41],[-0.093,-1.722],[1.724,-0.094],[6.003,-3.419],[3.674,-5.493]],"o":[[-0.995,0.567],[-1.433,-0.959],[4.21,-6.294],[6.841,-3.896],[1.722,-0.093],[0.094,1.722],[-6.599,0.357],[-6.003,3.418],[-0.279,0.417]],"v":[[-16.693,13.1],[-19.976,12.983],[-20.836,8.652],[-3.944,-6.925],[18.072,-13.506],[21.359,-10.556],[18.409,-7.27],[-0.853,-1.498],[-15.645,12.124]],"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":[[7.044,-4.012],[6.96,0.908],[-0.223,1.71],[-1.711,-0.224],[-5.298,3.017],[-2.065,5.824],[-1.624,-0.577],[0.576,-1.626]],"o":[[-6.489,3.695],[-1.71,-0.223],[0.223,-1.71],[5.601,0.73],[5.742,-3.27],[0.577,-1.625],[1.625,0.576],[-2.566,7.236]],"v":[[44.597,78.169],[24.039,82.43],[21.346,78.93],[24.846,76.237],[41.507,72.742],[53.614,58.64],[57.601,56.74],[59.5,60.727]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0.323,-0.184],[1.029,0.844],[0.13,0.229],[-15.469,8.81],[-8.28,-14.539],[1.498,-0.853],[0.853,1.498],[12.426,-7.076],[-6.547,-11.496],[-4.085,-3.35],[1.094,-1.333]],"o":[[-1.091,0.621],[-5.004,-4.103],[-8.28,-14.539],[15.469,-8.81],[0.853,1.498],[-1.498,0.853],[-6.547,-11.496],[-12.426,7.077],[0.024,0.042],[1.333,1.093],[-0.25,0.305]],"v":[[10.147,71.146],[6.621,70.847],[-1.636,61.086],[11.185,19.448],[53.537,29.665],[52.369,33.924],[48.111,32.756],[14.276,24.874],[3.791,57.996],[10.581,66.018],[11.016,70.413]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[1.183,-0.674],[0.287,-0.071],[3.505,8.779],[-6.102,3.475],[-3.887,-4.766],[0,0],[-3.067,1.747],[1.97,3.459],[0,0],[-1.498,0.853],[-0.853,-1.498],[0,0],[6.451,-3.674],[4.175,5.108],[0,0],[2.675,-1.523],[-1.489,-3.73],[-5.283,1.305],[-0.414,-1.674]],"o":[[-0.244,0.139],[-9.188,2.268],[-2.649,-6.633],[5.335,-3.038],[0,0],[2.235,2.735],[3.459,-1.97],[0,0],[-0.853,-1.498],[1.498,-0.853],[0,0],[3.674,6.452],[-5.725,3.26],[0,0],[-1.949,-2.391],[-3.377,1.923],[2.674,6.697],[1.674,-0.413],[0.342,1.387]],"v":[[36.276,64.961],[35.477,65.279],[11.151,49.991],[16.667,33.848],[32.582,36.831],[36.686,41.876],[45.842,43.586],[48.542,33.739],[47.994,32.777],[49.163,28.518],[53.421,29.686],[53.969,30.648],[48.932,49.012],[31.846,45.823],[27.739,40.774],[19.758,39.275],[16.951,47.675],[33.98,59.216],[37.761,61.499]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0.501,-0.285],[0.978,0.515],[11.066,-6.302],[0.514,-9.958],[1.721,0.088],[-0.089,1.722],[-13.068,7.442],[-10.828,-5.692],[0.802,-1.526]],"o":[[-0.895,0.51],[-8.827,-4.639],[-11.066,6.302],[-0.089,1.722],[-1.722,-0.089],[0.63,-12.217],[13.068,-7.442],[1.527,0.802],[-0.288,0.548]],"v":[[42.238,8.912],[39.237,8.964],[6.49,11.701],[-12.571,38.468],[-15.851,41.426],[-18.808,38.146],[3.4,6.274],[42.142,3.436],[43.453,7.653]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.596078455448,0.321568638086,0.239215686917,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":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":960,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Thumb","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[225.438,108.028,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],[42.783,10.613],[3.8,0.302],[0,0],[0.105,0.008],[0.484,0.019],[6.105,-2.438],[0,0],[0.032,-0.013],[0.85,-0.396],[0,0],[0,0],[0,0],[0,0],[-26.827,-45.427],[0,0],[0,0]],"o":[[-28.424,-53.851],[-3.608,-1.195],[0,0],[-0.106,-0.009],[-0.482,-0.035],[-6.685,-0.314],[0,0],[-0.032,0.013],[-0.853,0.343],[-20.172,9.126],[0,0],[-6.217,10.813],[0,0],[-5.276,37.379],[0,0],[0,0],[0,0]],"v":[[76.157,43.103],[-34.58,-89.69],[-45.717,-91.957],[-45.708,-91.966],[-46.022,-91.983],[-47.471,-92.063],[-66.474,-88.859],[-66.467,-88.866],[-66.56,-88.826],[-69.115,-87.715],[-94.124,-66.879],[-94.112,-66.885],[-101.514,-44.23],[-101.507,-44.234],[-53.003,92.116],[30.37,92.116],[102.173,92.116]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.678431391716,0.403921574354,0.305882364511,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":960,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".grey900","cl":"grey900","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,100,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":[{"ty":"rc","d":1,"s":{"a":0,"k":[412,200],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":38,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.1254902035,0.129411771894,0.141176477075,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":0,"op":960,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2057666..74b7dab 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6026,7 +6026,8 @@
<string name="help_uri_about" translatable="false"></string>
<!-- Help URI, manage apps that can set alarms and reminders [DO NOT TRANSLATE] -->
<string name="help_uri_alarms_and_reminders" translatable="false"></string>
-
+ <!-- Help URI, manage apps that can run long background tasks [DO NOT TRANSLATE] -->
+ <string name="help_uri_long_background_tasks" translatable="false"></string>
<!-- Help URL, WiFi [DO NOT TRANSLATE] -->
<string name="help_url_wifi" translatable="false"></string>
<!-- Help URL, WiFi Direct [DO NOT TRANSLATE] -->
@@ -9117,6 +9118,22 @@
<!-- Title for the See more preference item in Special app access settings [CHAR LIMIT=30] -->
<string name="special_access_more">See more</string>
+ <!-- Label for the settings activity for controlling apps that can run long background tasks [CHAR LIMIT=30] -->
+ <string name="long_background_tasks_label">Long background tasks</string>
+ <!-- Label for the switch to toggle the permission for running long background tasks [CHAR LIMIT=50] -->
+ <string name="long_background_tasks_switch_title">Allow long-running background tasks</string>
+ <!-- Title for the settings screen for controlling apps that can run long background tasks [CHAR LIMIT=30] -->
+ <string name="long_background_tasks_title">Long background tasks</string>
+ <!-- Description that appears below the long_background_tasks switch [CHAR LIMIT=NONE] -->
+ <string name="long_background_tasks_footer_title">
+ Allow this app to run long background tasks. This lets the app run tasks that might
+ take longer than a few minutes to finish, such as downloads and uploads.
+ \n\nIf this permission is denied, the system will limit how long the app can perform
+ such tasks in the background.
+ </string>
+ <!-- Keywords for settings screen for controlling apps that can run long background tasks [CHAR LIMIT=NONE] -->
+ <string name="keywords_long_background_tasks">long jobs, data transfer, background tasks</string>
+
<!-- Reset rate-limiting in the system service ShortcutManager. "ShortcutManager" is the name of a system service and not translatable.
If the word "rate-limit" is hard to translate, use "Reset ShortcutManager API call limit" as the source text, which means
the same thing in this context.
diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml
index 2bb05d0..e004f28 100644
--- a/res/xml/app_info_settings.xml
+++ b/res/xml/app_info_settings.xml
@@ -189,6 +189,12 @@
android:summary="@string/summary_placeholder"
settings:controller="com.android.settings.applications.appinfo.AlarmsAndRemindersDetailPreferenceController" />
+ <Preference
+ android:key="long_background_tasks"
+ android:title="@string/long_background_tasks_title"
+ android:summary="@string/summary_placeholder"
+ settings:controller="com.android.settings.applications.appinfo.LongBackgroundTasksDetailsPreferenceController" />
+
</PreferenceCategory>
<!-- App installer info -->
diff --git a/res/xml/long_background_tasks.xml b/res/xml/long_background_tasks.xml
new file mode 100644
index 0000000..405b0cf
--- /dev/null
+++ b/res/xml/long_background_tasks.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/long_background_tasks_title">
+
+ <com.android.settings.widget.FilterTouchesRestrictedSwitchPreference
+ android:key="long_background_tasks_switch"
+ android:title="@string/long_background_tasks_switch_title" />
+
+ <com.android.settingslib.widget.FooterPreference
+ android:key="long_background_tasks_description"
+ android:title="@string/long_background_tasks_footer_title"
+ android:selectable="false" />
+
+</PreferenceScreen>
diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml
index 3dd6e18..0d2ee51 100644
--- a/res/xml/special_access.xml
+++ b/res/xml/special_access.xml
@@ -108,6 +108,16 @@
settings:controller="com.android.settings.applications.specialaccess.DataSaverController" />
<Preference
+ android:key="long_background_tasks"
+ android:title="@string/long_background_tasks_title"
+ android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
+ settings:keywords="@string/keywords_long_background_tasks">
+ <extra
+ android:name="classname"
+ android:value="com.android.settings.Settings$LongBackgroundTasksActivity" />
+ </Preference>
+
+ <Preference
android:key="manage_external_sources"
android:title="@string/install_other_apps"
android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index 224ba13..7635041 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -24,8 +24,6 @@
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.telephony.SubscriptionInfo;
@@ -46,12 +44,10 @@
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
+import com.android.settings.network.ResetNetworkRestrictionViewBuilder;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
-import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.development.DevelopmentSettingsEnabler;
import java.util.ArrayList;
@@ -115,7 +111,7 @@
// confirmation prompt; otherwise, go back to the initial state.
if (resultCode == Activity.RESULT_OK) {
showFinalConfirmation();
- } else {
+ } else if (mContentView != null) {
establishInitialState(getActiveSubscriptionInfoList());
}
}
@@ -255,6 +251,10 @@
public void onResume() {
super.onResume();
+ if (mContentView == null) {
+ return;
+ }
+
// update options if subcription has been changed
List<SubscriptionInfo> updatedSubscriptions = getActiveSubscriptionInfoList();
if ((mSubscriptions != null)
@@ -283,18 +283,10 @@
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- final UserManager um = UserManager.get(getActivity());
- final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
- getActivity(), UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId());
- if (!um.isAdminUser() || RestrictedLockUtilsInternal.hasBaseUserRestriction(getActivity(),
- UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
- return inflater.inflate(R.layout.network_reset_disallowed_screen, null);
- } else if (admin != null) {
- new ActionDisabledByAdminDialogHelper(getActivity())
- .prepareDialogBuilder(UserManager.DISALLOW_NETWORK_RESET, admin)
- .setOnDismissListener(__ -> getActivity().finish())
- .show();
- return new View(getContext());
+ View view = (new ResetNetworkRestrictionViewBuilder(getActivity())).build();
+ if (view != null) {
+ Log.w(TAG, "Access deny.");
+ return view;
}
mContentView = inflater.inflate(R.layout.reset_network, null);
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index 30d159b..8926d5c 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -16,8 +16,6 @@
package com.android.settings;
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
import android.app.Activity;
import android.app.ProgressDialog;
import android.app.settings.SettingsEnums;
@@ -35,8 +33,6 @@
import android.os.Bundle;
import android.os.Looper;
import android.os.RecoverySystem;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
@@ -52,9 +48,8 @@
import androidx.appcompat.app.AlertDialog;
import com.android.settings.core.InstrumentedFragment;
-import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
+import com.android.settings.network.ResetNetworkRestrictionViewBuilder;
import com.android.settings.network.apn.ApnSettings;
-import com.android.settingslib.RestrictedLockUtilsInternal;
/**
* Confirm and execute a reset of the network settings to a clean "just out of the box"
@@ -262,17 +257,10 @@
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
- mActivity, UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId());
- if (RestrictedLockUtilsInternal.hasBaseUserRestriction(mActivity,
- UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
- return inflater.inflate(R.layout.network_reset_disallowed_screen, null);
- } else if (admin != null) {
- new ActionDisabledByAdminDialogHelper(mActivity)
- .prepareDialogBuilder(UserManager.DISALLOW_NETWORK_RESET, admin)
- .setOnDismissListener(__ -> mActivity.finish())
- .show();
- return new View(mActivity);
+ View view = (new ResetNetworkRestrictionViewBuilder(mActivity)).build();
+ if (view != null) {
+ Log.w(TAG, "Access deny.");
+ return view;
}
mContentView = inflater.inflate(R.layout.reset_network_confirm, null);
establishFinalConfirmationState();
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index b95c9b0..e394e45 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -430,6 +430,11 @@
}
}
+ /** Actviity to manage apps with {@link android.Manifest.permission#RUN_LONG_JOBS} */
+ public static class LongBackgroundTasksActivity extends SettingsActivity { /* empty */ }
+ /** App specific version of {@link LongBackgroundTasksActivity} */
+ public static class LongBackgroundTasksAppActivity extends SettingsActivity { /* empty */ }
+
/**
* Activity for BugReportHandlerPicker.
*/
diff --git a/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java b/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java
index c3359e4..04db825 100644
--- a/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java
@@ -41,6 +41,7 @@
import com.android.settings.R;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.accessibility.AccessibilityUtils;
import java.util.List;
@@ -230,6 +231,10 @@
new ComponentName(packageName, tileServiceClassName).flattenToString());
}
+ final int metricsCategory = FeatureFactory.getFactory(getActivity().getApplicationContext())
+ .getAccessibilityMetricsFeatureProvider()
+ .getDownloadedFeatureMetricsCategory(componentName);
+ extras.putInt(AccessibilitySettings.EXTRA_METRICS_CATEGORY, metricsCategory);
extras.putParcelable(AccessibilitySettings.EXTRA_COMPONENT_NAME, componentName);
extras.putInt(AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES, info.getAnimatedImageRes());
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 1008183..23f8fd3 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -87,6 +87,7 @@
static final String EXTRA_ANIMATED_IMAGE_RES = "animated_image_res";
static final String EXTRA_HTML_DESCRIPTION = "html_description";
static final String EXTRA_TIME_FOR_LOGGING = "start_time_to_log_a11y_tool";
+ static final String EXTRA_METRICS_CATEGORY = "metrics_category";
// Timeout before we update the services if packages are added/removed
// since the AccessibilityManagerService has to do that processing first
diff --git a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
index 1f8374d..80d1ce0 100644
--- a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
@@ -42,7 +42,6 @@
import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
-import com.android.settings.overlay.FeatureFactory;
import java.util.ArrayList;
import java.util.List;
@@ -58,15 +57,7 @@
@Override
public int getMetricsCategory() {
- // Retrieve from getArguments() directly because this function will be executed from
- // onAttach(), but variable mComponentName only available after onProcessArguments()
- // which comes from onCreateView().
- final ComponentName componentName = getArguments().getParcelable(
- AccessibilitySettings.EXTRA_COMPONENT_NAME);
-
- return FeatureFactory.getFactory(getActivity().getApplicationContext())
- .getAccessibilityMetricsFeatureProvider()
- .getDownloadedFeatureMetricsCategory(componentName);
+ return getArguments().getInt(AccessibilitySettings.EXTRA_METRICS_CATEGORY);
}
@Override
diff --git a/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java b/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java
index 4344acc..00339a1 100644
--- a/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java
+++ b/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java
@@ -37,6 +37,7 @@
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.RestrictedPreference;
@@ -118,9 +119,12 @@
final String htmlDescription = info.loadHtmlDescription(mPm);
final String settingsClassName = info.getSettingsActivityName();
final String tileServiceClassName = info.getTileServiceName();
+ final int metricsCategory = FeatureFactory.getFactory(mContext)
+ .getAccessibilityMetricsFeatureProvider()
+ .getDownloadedFeatureMetricsCategory(componentName);
putBasicExtras(preference, prefKey, title, intro, description, imageRes,
- htmlDescription, componentName);
+ htmlDescription, componentName, metricsCategory);
putServiceExtras(preference, resolveInfo, serviceEnabled);
putSettingsExtras(preference, packageName, settingsClassName);
putTileServiceExtras(preference, packageName, tileServiceClassName);
@@ -178,9 +182,12 @@
final String htmlDescription = info.loadHtmlDescription(mPm);
final String settingsClassName = info.getSettingsActivityName();
final String tileServiceClassName = info.getTileServiceName();
+ final int metricsCategory = FeatureFactory.getFactory(mContext)
+ .getAccessibilityMetricsFeatureProvider()
+ .getDownloadedFeatureMetricsCategory(componentName);
putBasicExtras(preference, prefKey, title, intro, description, imageRes,
- htmlDescription, componentName);
+ htmlDescription, componentName, metricsCategory);
putSettingsExtras(preference, componentName.getPackageName(), settingsClassName);
putTileServiceExtras(preference, componentName.getPackageName(),
tileServiceClassName);
@@ -265,7 +272,7 @@
/** Puts the basic extras into {@link RestrictedPreference}'s getExtras(). */
private void putBasicExtras(RestrictedPreference preference, String prefKey,
CharSequence title, CharSequence intro, CharSequence summary, int imageRes,
- String htmlDescription, ComponentName componentName) {
+ String htmlDescription, ComponentName componentName, int metricsCategory) {
final Bundle extras = preference.getExtras();
extras.putString(AccessibilitySettings.EXTRA_PREFERENCE_KEY, prefKey);
extras.putCharSequence(AccessibilitySettings.EXTRA_TITLE, title);
@@ -274,6 +281,7 @@
extras.putParcelable(AccessibilitySettings.EXTRA_COMPONENT_NAME, componentName);
extras.putInt(AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES, imageRes);
extras.putString(AccessibilitySettings.EXTRA_HTML_DESCRIPTION, htmlDescription);
+ extras.putInt(AccessibilitySettings.EXTRA_METRICS_CATEGORY, metricsCategory);
}
/**
diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
index f1c0202..5941170 100644
--- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
@@ -49,7 +49,6 @@
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;
import java.util.List;
@@ -71,15 +70,7 @@
@Override
public int getMetricsCategory() {
- // Retrieve from getArguments() directly because this function will be executed from
- // onAttach(), but variable mComponentName only available after onProcessArguments()
- // which comes from onCreateView().
- final ComponentName componentName = getArguments().getParcelable(
- AccessibilitySettings.EXTRA_COMPONENT_NAME);
-
- return FeatureFactory.getFactory(getActivity().getApplicationContext())
- .getAccessibilityMetricsFeatureProvider()
- .getDownloadedFeatureMetricsCategory(componentName);
+ return getArguments().getInt(AccessibilitySettings.EXTRA_METRICS_CATEGORY);
}
@Override
diff --git a/src/com/android/settings/applications/AppStateLongBackgroundTasksBridge.java b/src/com/android/settings/applications/AppStateLongBackgroundTasksBridge.java
new file mode 100644
index 0000000..d286c5e
--- /dev/null
+++ b/src/com/android/settings/applications/AppStateLongBackgroundTasksBridge.java
@@ -0,0 +1,132 @@
+/*
+ * 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.applications;
+
+import android.Manifest;
+import android.app.AppGlobals;
+import android.app.job.JobScheduler;
+import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.ApplicationsState.AppFilter;
+
+import libcore.util.EmptyArray;
+
+import java.util.List;
+
+/**
+ * Connects app op info to the ApplicationsState. Extends {@link AppStateAppOpsBridge} to tailor
+ * to the semantics of {@link Manifest.permission#RUN_LONG_JOBS}.
+ * Also provides app filters that can use the info.
+ */
+public class AppStateLongBackgroundTasksBridge extends AppStateBaseBridge {
+ private static final String PERMISSION = Manifest.permission.RUN_LONG_JOBS;
+ private static final String TAG = "LongBackgroundTasksBridge";
+
+ @VisibleForTesting
+ JobScheduler mJobScheduler;
+ @VisibleForTesting
+ String[] mRequesterPackages;
+
+ public AppStateLongBackgroundTasksBridge(Context context, ApplicationsState appState,
+ Callback callback) {
+ super(appState, callback);
+
+ mJobScheduler = context.getSystemService(JobScheduler.class);
+ final IPackageManager iPm = AppGlobals.getPackageManager();
+ try {
+ mRequesterPackages = iPm.getAppOpPermissionPackages(PERMISSION, context.getUserId());
+ } catch (RemoteException re) {
+ Log.e(TAG, "Cannot reach package manager", re);
+ mRequesterPackages = EmptyArray.STRING;
+ }
+ }
+
+ /**
+ * Returns information regarding {@link Manifest.permission#RUN_LONG_JOBS} for the given
+ * package and uid.
+ */
+ public LongBackgroundTasksState createPermissionState(String packageName, int uid) {
+ final int userId = UserHandle.getUserId(uid);
+
+ final boolean permissionRequested = ArrayUtils.contains(mRequesterPackages, packageName);
+ final boolean permissionGranted = mJobScheduler.hasRunLongJobsPermission(packageName,
+ userId);
+ return new LongBackgroundTasksState(permissionRequested, permissionGranted);
+ }
+
+ @Override
+ protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
+ app.extraInfo = createPermissionState(pkg, uid);
+ }
+
+ @Override
+ protected void loadAllExtraInfo() {
+ final List<AppEntry> allApps = mAppSession.getAllApps();
+ for (int i = 0; i < allApps.size(); i++) {
+ final AppEntry currentEntry = allApps.get(i);
+ updateExtraInfo(currentEntry, currentEntry.info.packageName, currentEntry.info.uid);
+ }
+ }
+
+ public static final AppFilter FILTER_LONG_JOBS_APPS = new AppFilter() {
+
+ @Override
+ public void init() {
+ }
+
+ @Override
+ public boolean filterApp(AppEntry info) {
+ if (info.extraInfo instanceof LongBackgroundTasksState) {
+ final LongBackgroundTasksState state = (LongBackgroundTasksState) info.extraInfo;
+ return state.shouldBeVisible();
+ }
+ return false;
+ }
+ };
+
+ /**
+ * Class to denote the state of an app regarding
+ * {@link Manifest.permission#RUN_LONG_JOBS}.
+ */
+ public static class LongBackgroundTasksState {
+ private boolean mPermissionRequested;
+ private boolean mPermissionGranted;
+
+ LongBackgroundTasksState(boolean permissionRequested, boolean permissionGranted) {
+ mPermissionRequested = permissionRequested;
+ mPermissionGranted = permissionGranted;
+ }
+
+ /** Should the app associated with this state appear on the Settings screen */
+ public boolean shouldBeVisible() {
+ return mPermissionRequested;
+ }
+
+ /** Is the permission granted to the app associated with this state */
+ public boolean isAllowed() {
+ return mPermissionGranted;
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
index 7049b56..4a00260 100644
--- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
+++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
@@ -215,10 +215,15 @@
alarmsAndReminders.setPackageName(packageName);
alarmsAndReminders.setParentFragment(this);
+ final LongBackgroundTasksDetailsPreferenceController longBackgroundTasks =
+ use(LongBackgroundTasksDetailsPreferenceController.class);
+ longBackgroundTasks.setPackageName(packageName);
+ longBackgroundTasks.setParentFragment(this);
+
final AdvancedAppInfoPreferenceCategoryController advancedAppInfo =
use(AdvancedAppInfoPreferenceCategoryController.class);
advancedAppInfo.setChildren(Arrays.asList(writeSystemSettings, drawOverlay, pip,
- externalSource, acrossProfiles, alarmsAndReminders));
+ externalSource, acrossProfiles, alarmsAndReminders, longBackgroundTasks));
advancedAppInfo.setAppEntry(mAppEntry);
final AppLocalePreferenceController appLocale =
diff --git a/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetails.java b/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetails.java
new file mode 100644
index 0000000..1e5d11a
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetails.java
@@ -0,0 +1,163 @@
+/*
+ * 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.applications.appinfo;
+
+import static android.app.Activity.RESULT_CANCELED;
+import static android.app.Activity.RESULT_OK;
+
+import android.app.AppOpsManager;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.Preference;
+import androidx.preference.Preference.OnPreferenceChangeListener;
+
+import com.android.settings.R;
+import com.android.settings.Settings;
+import com.android.settings.applications.AppInfoWithHeader;
+import com.android.settings.applications.AppStateLongBackgroundTasksBridge;
+import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+
+/**
+ * App specific activity to show details about
+ * {@link android.Manifest.permission#RUN_LONG_JOBS}.
+ */
+public class LongBackgroundTasksDetails extends AppInfoWithHeader
+ implements OnPreferenceChangeListener {
+
+ private static final String KEY_SWITCH = "long_background_tasks_switch";
+ private static final String UNCOMMITTED_STATE_KEY = "uncommitted_state";
+
+ private AppStateLongBackgroundTasksBridge mAppBridge;
+ private AppOpsManager mAppOpsManager;
+ private RestrictedSwitchPreference mSwitchPref;
+ private AppStateLongBackgroundTasksBridge.LongBackgroundTasksState mPermissionState;
+ private volatile Boolean mUncommittedState;
+
+ /**
+ * Returns the string that states whether the app has access to
+ * {@link android.Manifest.permission#RUN_LONG_JOBS}.
+ */
+ public static CharSequence getSummary(Context context, AppEntry entry) {
+ final AppStateLongBackgroundTasksBridge.LongBackgroundTasksState state =
+ new AppStateLongBackgroundTasksBridge(context, /*appState=*/null,
+ /*callback=*/null).createPermissionState(entry.info.packageName,
+ entry.info.uid);
+
+ return context.getString(state.isAllowed() ? R.string.app_permission_summary_allowed
+ : R.string.app_permission_summary_not_allowed);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Context context = getActivity();
+ mAppBridge = new AppStateLongBackgroundTasksBridge(context, mState, /*callback=*/null);
+ mAppOpsManager = context.getSystemService(AppOpsManager.class);
+
+ if (savedInstanceState != null) {
+ mUncommittedState = (Boolean) savedInstanceState.get(UNCOMMITTED_STATE_KEY);
+ if (mUncommittedState != null && isAppSpecific()) {
+ setResult(mUncommittedState ? RESULT_OK : RESULT_CANCELED);
+ }
+ }
+ addPreferencesFromResource(R.xml.long_background_tasks);
+ mSwitchPref = findPreference(KEY_SWITCH);
+ mSwitchPref.setOnPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ if (mUncommittedState != null) {
+ outState.putObject(UNCOMMITTED_STATE_KEY, mUncommittedState);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference == mSwitchPref) {
+ mUncommittedState = (Boolean) newValue;
+ if (isAppSpecific()) {
+ setResult(mUncommittedState ? RESULT_OK : RESULT_CANCELED);
+ }
+ refreshUi();
+ return true;
+ }
+ return false;
+ }
+
+ private void setCanRunLongJobs(boolean newState) {
+ final int uid = mPackageInfo.applicationInfo.uid;
+ mAppOpsManager.setUidMode(AppOpsManager.OPSTR_RUN_LONG_JOBS, uid,
+ newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_ERRORED);
+ }
+
+ private void logPermissionChange(boolean newState, String packageName) {
+ mMetricsFeatureProvider.action(
+ mMetricsFeatureProvider.getAttribution(getActivity()),
+ SettingsEnums.ACTION_LONG_BACKGROUND_TASKS_TOGGLE,
+ getMetricsCategory(),
+ packageName,
+ newState ? 1 : 0);
+ }
+
+ private boolean isAppSpecific() {
+ return Settings.LongBackgroundTasksAppActivity.class.getName().equals(
+ getIntent().getComponent().getClassName());
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (getActivity().isChangingConfigurations()) {
+ return;
+ }
+ if (mPermissionState != null && mUncommittedState != null
+ && mUncommittedState != mPermissionState.isAllowed()) {
+ setCanRunLongJobs(mUncommittedState);
+ logPermissionChange(mUncommittedState, mPackageName);
+ mUncommittedState = null;
+ }
+ }
+
+ @Override
+ protected boolean refreshUi() {
+ if (mPackageInfo == null || mPackageInfo.applicationInfo == null) {
+ return false;
+ }
+ mPermissionState = mAppBridge.createPermissionState(mPackageName,
+ mPackageInfo.applicationInfo.uid);
+ mSwitchPref.setEnabled(mPermissionState.shouldBeVisible());
+ mSwitchPref.setChecked(
+ mUncommittedState != null ? mUncommittedState : mPermissionState.isAllowed());
+ return true;
+ }
+
+ @Override
+ protected AlertDialog createDialog(int id, int errorCode) {
+ return null;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.LONG_BACKGROUND_TASKS;
+ }
+}
diff --git a/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetailsPreferenceController.java b/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetailsPreferenceController.java
new file mode 100644
index 0000000..a41280b
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetailsPreferenceController.java
@@ -0,0 +1,77 @@
+/*
+ * 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.applications.appinfo;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.applications.AppStateLongBackgroundTasksBridge;
+
+/**
+ * Preference controller for
+ * {@link LongBackgroundTasksDetails} Settings fragment.
+ */
+public class LongBackgroundTasksDetailsPreferenceController extends
+ AppInfoPreferenceControllerBase {
+
+ private String mPackageName;
+
+ public LongBackgroundTasksDetailsPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return isCandidate() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ preference.setSummary(getPreferenceSummary());
+ }
+
+ @Override
+ protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
+ return LongBackgroundTasksDetails.class;
+ }
+
+ @VisibleForTesting
+ CharSequence getPreferenceSummary() {
+ return LongBackgroundTasksDetails.getSummary(mContext, mParent.getAppEntry());
+ }
+
+ @VisibleForTesting
+ boolean isCandidate() {
+ final PackageInfo packageInfo = mParent.getPackageInfo();
+ if (packageInfo == null) {
+ return false;
+ }
+ final AppStateLongBackgroundTasksBridge.LongBackgroundTasksState appState =
+ new AppStateLongBackgroundTasksBridge(
+ mContext, /*appState=*/null, /*callback=*/null)
+ .createPermissionState(mPackageName, packageInfo.applicationInfo.uid);
+ return appState.shouldBeVisible();
+ }
+
+ void setPackageName(String packageName) {
+ mPackageName = packageName;
+ }
+}
diff --git a/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java b/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java
index 15cf8e7..b48bdbb 100644
--- a/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java
+++ b/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java
@@ -23,6 +23,7 @@
import com.android.settings.applications.AppStateAppBatteryUsageBridge;
import com.android.settings.applications.AppStateInstallAppsBridge;
import com.android.settings.applications.AppStateLocaleBridge;
+import com.android.settings.applications.AppStateLongBackgroundTasksBridge;
import com.android.settings.applications.AppStateManageExternalStorageBridge;
import com.android.settings.applications.AppStateMediaManagementAppsBridge;
import com.android.settings.applications.AppStateNotificationBridge;
@@ -61,6 +62,7 @@
FILTER_APPS_BATTERY_UNRESTRICTED,
FILTER_APPS_BATTERY_OPTIMIZED,
FILTER_APPS_BATTERY_RESTRICTED,
+ FILTER_LONG_BACKGROUND_TASKS,
})
@interface FilterType {}
@@ -89,8 +91,9 @@
public static final int FILTER_APPS_BATTERY_UNRESTRICTED = 21;
public static final int FILTER_APPS_BATTERY_OPTIMIZED = 22;
public static final int FILTER_APPS_BATTERY_RESTRICTED = 23;
- // Next id: 24. If you add an entry here, please change NUM_FILTER_ENTRIES.
- private static final int NUM_FILTER_ENTRIES = 24;
+ public static final int FILTER_LONG_BACKGROUND_TASKS = 24;
+ // Next id: 25. If you add an entry here, please change NUM_FILTER_ENTRIES.
+ private static final int NUM_FILTER_ENTRIES = 25;
private static AppFilterRegistry sRegistry;
@@ -242,6 +245,12 @@
AppStateAppBatteryUsageBridge.FILTER_BATTERY_RESTRICTED_APPS,
FILTER_APPS_BATTERY_RESTRICTED,
R.string.filter_battery_restricted_title);
+
+ // Apps that can run long background tasks
+ mFilters[FILTER_LONG_BACKGROUND_TASKS] = new AppFilterItem(
+ AppStateLongBackgroundTasksBridge.FILTER_LONG_JOBS_APPS,
+ FILTER_LONG_BACKGROUND_TASKS,
+ R.string.long_background_tasks_title);
}
@@ -280,6 +289,8 @@
return FILTER_APPS_LOCALE;
case ManageApplications.LIST_TYPE_BATTERY_OPTIMIZATION:
return FILTER_APPS_BATTERY_OPTIMIZED;
+ case ManageApplications.LIST_TYPE_LONG_BACKGROUND_TASKS:
+ return FILTER_LONG_BACKGROUND_TASKS;
default:
return FILTER_APPS_ALL;
}
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index a41230a..e129954 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -94,6 +94,7 @@
import com.android.settings.Settings.ChangeWifiStateActivity;
import com.android.settings.Settings.GamesStorageActivity;
import com.android.settings.Settings.HighPowerApplicationsActivity;
+import com.android.settings.Settings.LongBackgroundTasksActivity;
import com.android.settings.Settings.ManageExternalSourcesActivity;
import com.android.settings.Settings.ManageExternalStorageActivity;
import com.android.settings.Settings.MediaManagementAppsActivity;
@@ -112,6 +113,7 @@
import com.android.settings.applications.AppStateBaseBridge;
import com.android.settings.applications.AppStateInstallAppsBridge;
import com.android.settings.applications.AppStateLocaleBridge;
+import com.android.settings.applications.AppStateLongBackgroundTasksBridge;
import com.android.settings.applications.AppStateManageExternalStorageBridge;
import com.android.settings.applications.AppStateMediaManagementAppsBridge;
import com.android.settings.applications.AppStateNotificationBridge;
@@ -128,6 +130,7 @@
import com.android.settings.applications.appinfo.AppLocaleDetails;
import com.android.settings.applications.appinfo.DrawOverlayDetails;
import com.android.settings.applications.appinfo.ExternalSourcesDetails;
+import com.android.settings.applications.appinfo.LongBackgroundTasksDetails;
import com.android.settings.applications.appinfo.ManageExternalStorageDetails;
import com.android.settings.applications.appinfo.MediaManagementAppsDetails;
import com.android.settings.applications.appinfo.WriteSettingsDetails;
@@ -256,6 +259,7 @@
public static final int LIST_TYPE_MEDIA_MANAGEMENT_APPS = 13;
public static final int LIST_TYPE_APPS_LOCALE = 14;
public static final int LIST_TYPE_BATTERY_OPTIMIZATION = 15;
+ public static final int LIST_TYPE_LONG_BACKGROUND_TASKS = 16;
// List types that should show instant apps.
public static final Set<Integer> LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
@@ -402,6 +406,8 @@
mListType = LIST_TYPE_APPS_LOCALE;
} else if (className.equals(AppBatteryUsageActivity.class.getName())) {
mListType = LIST_TYPE_BATTERY_OPTIMIZATION;
+ } else if (className.equals(LongBackgroundTasksActivity.class.getName())) {
+ mListType = LIST_TYPE_LONG_BACKGROUND_TASKS;
} else {
mListType = LIST_TYPE_MAIN;
}
@@ -598,6 +604,8 @@
return SettingsEnums.APPS_LOCALE_LIST;
case LIST_TYPE_BATTERY_OPTIMIZATION:
return SettingsEnums.BATTERY_OPTIMIZED_APPS_LIST;
+ case LIST_TYPE_LONG_BACKGROUND_TASKS:
+ return SettingsEnums.LONG_BACKGROUND_TASKS;
default:
return SettingsEnums.PAGE_UNKNOWN;
}
@@ -735,6 +743,10 @@
getActivity(), this, mCurrentPkgName,
UserHandle.getUserHandleForUid(mCurrentUid));
break;
+ case LIST_TYPE_LONG_BACKGROUND_TASKS:
+ startAppInfoFragment(LongBackgroundTasksDetails.class,
+ R.string.long_background_tasks_label);
+ break;
// TODO: Figure out if there is a way where we can spin up the profile's settings
// process ahead of time, to avoid a long load of data when user clicks on a managed
// app. Maybe when they load the list of apps that contains managed profile apps.
@@ -828,6 +840,8 @@
return R.string.help_uri_alarms_and_reminders;
case LIST_TYPE_MEDIA_MANAGEMENT_APPS:
return R.string.help_uri_media_management_apps;
+ case LIST_TYPE_LONG_BACKGROUND_TASKS:
+ return R.string.help_uri_long_background_tasks;
default:
case LIST_TYPE_MAIN:
return R.string.help_uri_apps;
@@ -1030,6 +1044,8 @@
screenTitle = R.string.app_locales_picker_menu_title;
} else if (className.equals(AppBatteryUsageActivity.class.getName())) {
screenTitle = R.string.app_battery_usage_title;
+ } else if (className.equals(LongBackgroundTasksActivity.class.getName())) {
+ screenTitle = R.string.long_background_tasks_title;
} else {
if (screenTitle == -1) {
screenTitle = R.string.all_apps;
@@ -1233,6 +1249,8 @@
mManageApplications.mUserManager);
} else if (mManageApplications.mListType == LIST_TYPE_BATTERY_OPTIMIZATION) {
mExtraInfoBridge = new AppStateAppBatteryUsageBridge(mContext, mState, this);
+ } else if (mManageApplications.mListType == LIST_TYPE_LONG_BACKGROUND_TASKS) {
+ mExtraInfoBridge = new AppStateLongBackgroundTasksBridge(mContext, mState, this);
} else {
mExtraInfoBridge = null;
}
@@ -1762,6 +1780,9 @@
case LIST_TYPE_BATTERY_OPTIMIZATION:
holder.setSummary(null);
break;
+ case LIST_TYPE_LONG_BACKGROUND_TASKS:
+ holder.setSummary(LongBackgroundTasksDetails.getSummary(mContext, entry));
+ break;
default:
holder.updateSizeText(entry, mManageApplications.mInvalidSizeStr, mWhichSize);
break;
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index 112385f..fbc09d2 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -26,7 +26,6 @@
import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.face.FaceManager;
-import android.hardware.face.FaceSensorPropertiesInternal;
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
@@ -56,8 +55,6 @@
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.span.LinkSpan;
-import java.util.List;
-
/**
* Provides introductory info about face unlock and prompts the user to agree before starting face
* enrollment.
@@ -311,20 +308,12 @@
}
private boolean maxFacesEnrolled() {
- final boolean isSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
if (mFaceManager != null) {
- final List<FaceSensorPropertiesInternal> props =
- mFaceManager.getSensorPropertiesInternal();
// This will need to be updated for devices with multiple face sensors.
- final int max = props.get(0).maxEnrollmentsPerUser;
final int numEnrolledFaces = mFaceManager.getEnrolledFaces(mUserId).size();
- final int maxFacesEnrollableIfSUW = getApplicationContext().getResources()
+ final int maxFacesEnrollable = getApplicationContext().getResources()
.getInteger(R.integer.suw_max_faces_enrollable);
- if (isSetupWizard) {
- return numEnrolledFaces >= maxFacesEnrollableIfSUW;
- } else {
- return numEnrolledFaces >= max;
- }
+ return numEnrolledFaces >= maxFacesEnrollable;
} else {
return false;
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index bacb65e..3ab2f92 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -178,6 +178,8 @@
private boolean mHaveShownUdfpsTipLottie;
private boolean mHaveShownUdfpsLeftEdgeLottie;
private boolean mHaveShownUdfpsRightEdgeLottie;
+ private boolean mHaveShownUdfpsCenterLottie;
+ private boolean mHaveShownUdfpsGuideLottie;
private boolean mHaveShownSfpsNoAnimationLottie;
private boolean mHaveShownSfpsCenterLottie;
private boolean mHaveShownSfpsTipLottie;
@@ -508,18 +510,31 @@
switch (getCurrentStage()) {
case STAGE_CENTER:
setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
- setDescriptionText(R.string.security_settings_udfps_enroll_start_message);
+ if (mIsAccessibilityEnabled || mIllustrationLottie == null) {
+ setDescriptionText(R.string.security_settings_udfps_enroll_start_message);
+ } else if (!mHaveShownUdfpsCenterLottie && mIllustrationLottie != null) {
+ mHaveShownUdfpsCenterLottie = true;
+ // Note: Update string reference when differentiate in between udfps & sfps
+ mIllustrationLottie.setContentDescription(
+ getString(R.string.security_settings_sfps_enroll_finger_center_title)
+ );
+ configureEnrollmentStage("", R.raw.udfps_center_hint_lottie);
+ }
break;
case STAGE_GUIDED:
setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
- if (mIsAccessibilityEnabled) {
+ if (mIsAccessibilityEnabled || mIllustrationLottie == null) {
setDescriptionText(R.string.security_settings_udfps_enroll_repeat_a11y_message);
- } else {
- setDescriptionText(R.string.security_settings_udfps_enroll_repeat_message);
+ } else if (!mHaveShownUdfpsGuideLottie && mIllustrationLottie != null) {
+ mHaveShownUdfpsGuideLottie = true;
+ mIllustrationLottie.setContentDescription(
+ getString(R.string.security_settings_fingerprint_enroll_repeat_message)
+ );
+ // TODO(b/228100413) Could customize guided lottie animation
+ configureEnrollmentStage("", R.raw.udfps_center_hint_lottie);
}
break;
-
case STAGE_FINGERTIP:
setHeaderText(R.string.security_settings_udfps_enroll_fingertip_title);
if (!mHaveShownUdfpsTipLottie && mIllustrationLottie != null) {
@@ -530,7 +545,6 @@
configureEnrollmentStage("", R.raw.udfps_tip_hint_lottie);
}
break;
-
case STAGE_LEFT_EDGE:
setHeaderText(R.string.security_settings_udfps_enroll_left_edge_title);
if (!mHaveShownUdfpsLeftEdgeLottie && mIllustrationLottie != null) {
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index ce8739b..4cab05b 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -448,7 +448,8 @@
mFooterColumns.add(column2);
} else {
final FooterColumn column = new FooterColumn();
- column.mTitle = getText(R.string.security_settings_fingerprint_v2_home_screen_text);
+ column.mTitle = getText(
+ R.string.security_settings_fingerprint_enroll_introduction_v2_message);
column.mLearnMoreClickListener = learnMoreClickListener;
mFooterColumns.add(column);
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java
index 18db774..32b8300 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java
@@ -16,13 +16,17 @@
package com.android.settings.biometrics.fingerprint;
+import static android.util.FeatureFlagUtils.SETTINGS_BIOMETRICS2_ENROLLMENT;
+
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.fingerprint.FingerprintManager;
+import android.util.FeatureFlagUtils;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.ParentalControlsUtils;
+import com.android.settings.biometrics2.ui.view.FingerprintEnrollmentActivity;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
/**
@@ -79,7 +83,9 @@
*/
public String getSettingsClassName() {
return !hasEnrolled() && isAvailable()
- ? FingerprintEnrollIntroductionInternal.class.getName()
+ ? (FeatureFlagUtils.isEnabled(mContext, SETTINGS_BIOMETRICS2_ENROLLMENT)
+ ? FingerprintEnrollmentActivity.class.getName()
+ : FingerprintEnrollIntroductionInternal.class.getName())
: FingerprintSettings.class.getName();
}
diff --git a/src/com/android/settings/biometrics2/OWNERS b/src/com/android/settings/biometrics2/OWNERS
new file mode 100644
index 0000000..a257ed8
--- /dev/null
+++ b/src/com/android/settings/biometrics2/OWNERS
@@ -0,0 +1 @@
+include /src/com/android/settings/biometrics/OWNERS
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java
index e788da5..2308f2e 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java
@@ -89,7 +89,7 @@
@Nullable Bundle savedInstanceState) {
final Context context = inflater.getContext();
- mView = inflater.inflate(R.layout.fingerprint_enroll_introduction, container);
+ mView = inflater.inflate(R.layout.fingerprint_enroll_introduction, container, false);
final ImageView iconFingerprint = mView.findViewById(R.id.icon_fingerprint);
final ImageView iconDeviceLocked = mView.findViewById(R.id.icon_device_locked);
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index b55b024..7904fdb 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -48,6 +48,7 @@
import com.android.settings.applications.appinfo.AppLocaleDetails;
import com.android.settings.applications.appinfo.DrawOverlayDetails;
import com.android.settings.applications.appinfo.ExternalSourcesDetails;
+import com.android.settings.applications.appinfo.LongBackgroundTasksDetails;
import com.android.settings.applications.appinfo.ManageExternalStorageDetails;
import com.android.settings.applications.appinfo.MediaManagementAppsDetails;
import com.android.settings.applications.appinfo.WriteSettingsDetails;
@@ -357,7 +358,8 @@
TurnScreenOnSettings.class.getName(),
TurnScreenOnDetails.class.getName(),
NfcAndPaymentFragment.class.getName(),
- ColorAndMotionFragment.class.getName()
+ ColorAndMotionFragment.class.getName(),
+ LongBackgroundTasksDetails.class.getName()
};
public static final String[] SETTINGS_FOR_RESTRICTED = {
diff --git a/src/com/android/settings/deviceinfo/StorageCategoryFragment.java b/src/com/android/settings/deviceinfo/StorageCategoryFragment.java
index 31b73bc..d1c8029 100644
--- a/src/com/android/settings/deviceinfo/StorageCategoryFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageCategoryFragment.java
@@ -26,7 +26,6 @@
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.util.SparseArray;
-import android.view.View;
import androidx.annotation.VisibleForTesting;
import androidx.loader.app.LoaderManager;
@@ -210,9 +209,7 @@
return;
}
- if (getView().findViewById(R.id.loading_container).getVisibility() == View.VISIBLE) {
- setLoading(false /* loading */, true /* animate */);
- }
+ setLoading(false /* loading */, false /* animate */);
final long privateUsedBytes = mStorageInfo.totalBytes - mStorageInfo.freeBytes;
mPreferenceController.setVolume(mSelectedStorageEntry.getVolumeInfo());
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 368ba91..f31f2be 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -385,7 +385,7 @@
return;
}
- setLoading(false /* loading */, true /* animate */);
+ setLoading(false /* loading */, false /* animate */);
final long privateUsedBytes = mStorageInfo.totalBytes - mStorageInfo.freeBytes;
mPreferenceController.setVolume(mSelectedStorageEntry.getVolumeInfo());
diff --git a/src/com/android/settings/network/MobileNetworkRepository.java b/src/com/android/settings/network/MobileNetworkRepository.java
index 038490f..677e5f4 100644
--- a/src/com/android/settings/network/MobileNetworkRepository.java
+++ b/src/com/android/settings/network/MobileNetworkRepository.java
@@ -39,6 +39,7 @@
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settingslib.mobile.dataservice.DataServiceUtils;
import com.android.settingslib.mobile.dataservice.MobileNetworkDatabase;
import com.android.settingslib.mobile.dataservice.MobileNetworkInfoDao;
import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
@@ -49,6 +50,7 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
@@ -98,21 +100,29 @@
public static MobileNetworkRepository create(Context context,
MobileNetworkCallback mobileNetworkCallback) {
- return new MobileNetworkRepository(context, mobileNetworkCallback);
+ return new MobileNetworkRepository(context, mobileNetworkCallback,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
}
- private MobileNetworkRepository(Context context, MobileNetworkCallback mobileNetworkCallback) {
+ public static MobileNetworkRepository createBySubId(Context context,
+ MobileNetworkCallback mobileNetworkCallback, int subId) {
+ return new MobileNetworkRepository(context, mobileNetworkCallback, subId);
+ }
+
+ private MobileNetworkRepository(Context context, MobileNetworkCallback mobileNetworkCallback,
+ int subId) {
+ mSubId = subId;
mContext = context;
- mCallback = mobileNetworkCallback;
mMobileNetworkDatabase = MobileNetworkDatabase.getInstance(context);
+ mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+ mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_MOBILE_NETWORK_DB_CREATED);
+ mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
+ mCallback = mobileNetworkCallback;
mSubscriptionInfoDao = mMobileNetworkDatabase.mSubscriptionInfoDao();
mUiccInfoDao = mMobileNetworkDatabase.mUiccInfoDao();
mMobileNetworkInfoDao = mMobileNetworkDatabase.mMobileNetworkInfoDao();
- mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mAirplaneModeObserver = new AirplaneModeObserver(new Handler(Looper.getMainLooper()));
mAirplaneModeSettingUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
- mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
- mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_MOBILE_NETWORK_DB_CREATED);
mFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
mFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED);
}
@@ -205,6 +215,10 @@
return mSubscriptionInfoDao.querySubInfoById(subId);
}
+ public MobileNetworkInfoEntity queryMobileNetworkInfoBySubId(String subId) {
+ return mMobileNetworkInfoDao.queryMobileNetworkInfoBySubId(subId);
+ }
+
public int getSubInfosCount() {
return mSubscriptionInfoDao.count();
}
@@ -222,26 +236,26 @@
for (int i = 0; i < uiccSlotInfos.length; i++) {
UiccSlotInfo curSlotInfo = uiccSlotInfos[i];
if (curSlotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT) {
+ final int index = i;
mIsEuicc = curSlotInfo.getIsEuicc();
mCardState = curSlotInfo.getCardStateInfo();
mIsRemovable = curSlotInfo.isRemovable();
mCardId = subInfo.getCardId();
Collection<UiccPortInfo> uiccPortInfos = curSlotInfo.getPorts();
- for (UiccPortInfo portInfo : uiccPortInfos) {
+ uiccPortInfos.forEach(portInfo -> {
if (portInfo.getPortIndex() == subInfo.getPortIndex()
&& portInfo.getLogicalSlotIndex() == subInfo.getSimSlotIndex()) {
- mPhysicalSlotIndex = i;
+ mPhysicalSlotIndex = index;
mLogicalSlotIndex = portInfo.getLogicalSlotIndex();
mIsActive = portInfo.isActive();
mPortIndex = portInfo.getPortIndex();
- break;
} else if (DEBUG) {
Log.d(TAG,
"Can not get port index and physicalSlotIndex for subId "
+ mSubId);
}
- }
+ });
if (mPhysicalSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
break;
}
@@ -398,7 +412,8 @@
MobileNetworkUtils.shouldDisplayNetworkSelectOptions(context, mSubId),
MobileNetworkUtils.isTdscdmaSupported(context, mSubId),
MobileNetworkUtils.activeNetworkIsCellular(context),
- SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager)
+ SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager),
+ mTelephonyManager.isDataRoamingEnabled()
);
}
@@ -446,9 +461,10 @@
}
if (!mSubscriptionInfoMap.isEmpty()) {
- mSubscriptionInfoMap.forEach((key, value) -> {
- deleteAllInfoBySubId(String.valueOf(key));
- });
+ Iterator<Integer> iterator = mSubscriptionInfoMap.keySet().iterator();
+ while (iterator.hasNext()) {
+ deleteAllInfoBySubId(String.valueOf(iterator.next()));
+ }
}
}
}
diff --git a/src/com/android/settings/network/ResetNetworkRestrictionViewBuilder.java b/src/com/android/settings/network/ResetNetworkRestrictionViewBuilder.java
new file mode 100644
index 0000000..4f730fb
--- /dev/null
+++ b/src/com/android/settings/network/ResetNetworkRestrictionViewBuilder.java
@@ -0,0 +1,118 @@
+/*
+ * 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.network;
+
+import android.app.Activity;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewStub;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settings.R;
+import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+/**
+ * A builder for creating restriction View when constructing UI for resetting network
+ * configuration.
+ */
+public class ResetNetworkRestrictionViewBuilder extends NetworkResetRestrictionChecker {
+
+ @VisibleForTesting
+ static final String mRestriction = UserManager.DISALLOW_NETWORK_RESET;
+
+ protected Activity mActivity;
+ protected LayoutInflater mInflater;
+
+ /**
+ * Constructor of builder.
+ *
+ * @param activity Activity to present restriction View.
+ */
+ public ResetNetworkRestrictionViewBuilder(Activity activity) {
+ super(activity);
+ mActivity = activity;
+ }
+
+ /**
+ * Option for configuring LayoutInflater.
+ *
+ * @param inflater LayoutInflater
+ * @return this builder
+ */
+ public ResetNetworkRestrictionViewBuilder setLayoutInflater(LayoutInflater inflater) {
+ mInflater = inflater;
+ return this;
+ }
+
+ /**
+ * Try to provide a View if access to reset network is not allowed.
+ * @return a View which presenting information of restrictions.
+ * {@code null} when no restriction on accessing.
+ */
+ public View build() {
+ if (hasUserRestriction()) {
+ return operationNotAllow();
+ }
+
+ // Not allow when this option is restricted.
+ EnforcedAdmin admin = getEnforceAdminByRestriction();
+ if (admin == null) {
+ return null;
+ }
+
+ createRestrictDialogBuilder(admin)
+ .setOnDismissListener(dialogInterface -> mActivity.finish())
+ .show();
+ return createEmptyView();
+ }
+
+ @VisibleForTesting
+ protected LayoutInflater getLayoutInflater() {
+ if (mInflater != null) {
+ return mInflater;
+ }
+ return mActivity.getLayoutInflater();
+ }
+
+ @VisibleForTesting
+ protected View operationNotAllow() {
+ return getLayoutInflater().inflate(R.layout.network_reset_disallowed_screen, null);
+ }
+
+ @VisibleForTesting
+ protected EnforcedAdmin getEnforceAdminByRestriction() {
+ return RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
+ mActivity, mRestriction, UserHandle.myUserId());
+ }
+
+ @VisibleForTesting
+ protected AlertDialog.Builder createRestrictDialogBuilder(EnforcedAdmin admin) {
+ return (new ActionDisabledByAdminDialogHelper(mActivity))
+ .prepareDialogBuilder(mRestriction, admin);
+ }
+
+ @VisibleForTesting
+ protected View createEmptyView() {
+ return new ViewStub(mActivity);
+ }
+}
diff --git a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
index da81213..f4543f5 100644
--- a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
+++ b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
@@ -99,7 +99,7 @@
@Override
public boolean isChecked() {
- return mManager.isMobileDataPolicyEnabled(
+ return mManager != null && mManager.isMobileDataPolicyEnabled(
TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH);
}
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
index 2525fbd..1aca6b9 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@@ -135,6 +135,11 @@
@Override
public void updateState(Preference preference) {
super.updateState(preference);
+
+ if (mBuilder == null) {
+ return;
+ }
+
final ListPreference listPreference = (ListPreference) preference;
mBuilder.setPreferenceEntries();
@@ -871,6 +876,8 @@
@Override
public void onSubscriptionsChanged() {
- mBuilder.updateConfig();
+ if (mBuilder != null) {
+ mBuilder.updateConfig();
+ }
}
}
diff --git a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java
index 85d6e73..5908ecd 100644
--- a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java
+++ b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java
@@ -96,7 +96,8 @@
@Override
public boolean isChecked() {
- return mTelephonyManager.isDataEnabledForApn(ApnSetting.TYPE_MMS);
+ return mTelephonyManager != null && mTelephonyManager.isDataEnabledForApn(
+ ApnSetting.TYPE_MMS);
}
private void refreshPreference() {
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index a0c9679..97ba8b8 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -23,7 +23,6 @@
import android.os.Bundle;
import android.os.UserManager;
import android.provider.Settings;
-import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -40,8 +39,8 @@
import com.android.settings.SettingsActivity;
import com.android.settings.datausage.BillingCyclePreferenceController;
import com.android.settings.datausage.DataUsageSummaryPreferenceController;
-import com.android.settings.network.ActiveSubscriptionsListener;
import com.android.settings.network.CarrierWifiTogglePreferenceController;
+import com.android.settings.network.MobileNetworkRepository;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.network.telephony.cdma.CdmaSubscriptionPreferenceController;
import com.android.settings.network.telephony.cdma.CdmaSystemSelectPreferenceController;
@@ -50,15 +49,26 @@
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.wifi.WifiPickerTrackerHelper;
import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.mobile.dataservice.DataServiceUtils;
+import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
+import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
+import com.android.settingslib.mobile.dataservice.UiccInfoEntity;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.utils.ThreadUtils;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.function.Consumer;
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
-public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
+public class MobileNetworkSettings extends AbstractMobileNetworkSettings implements
+ MobileNetworkRepository.MobileNetworkCallback {
private static final String LOG_TAG = "NetworkSettings";
public static final int REQUEST_CODE_EXIT_ECM = 17;
@@ -66,10 +76,14 @@
@VisibleForTesting
static final String KEY_CLICKED_PREF = "key_clicked_pref";
+ private static final String KEY_ROAMING_PREF = "button_roaming_key";
+
//String keys for preference lookup
private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key";
private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key";
+ private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
+
private TelephonyManager mTelephonyManager;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -79,9 +93,11 @@
private UserManager mUserManager;
private String mClickedPrefKey;
- private ActiveSubscriptionsListener mActiveSubscriptionsListener;
- private boolean mDropFirstSubscriptionChangeNotify;
- private int mActiveSubscriptionsListenerCount;
+ private MobileNetworkRepository mMobileNetworkRepository;
+ private List<SubscriptionInfoEntity> mSubInfoEntityList = new ArrayList<>();
+ private Map<Integer, SubscriptionInfoEntity> mSubscriptionInfoMap = new HashMap<>();
+ private SubscriptionInfoEntity mSubscriptionInfoEntity;
+ private MobileNetworkInfoEntity mMobileNetworkInfoEntity;
public MobileNetworkSettings() {
super(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
@@ -138,12 +154,21 @@
MobileNetworkUtils.getSearchableSubscriptionId(context));
Log.d(LOG_TAG, "display subId from getArguments(): " + mSubId);
}
-
- if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
+ mMobileNetworkRepository = MobileNetworkRepository.create(context, this);
+ mExecutor.execute(() -> {
+ mSubscriptionInfoEntity = mMobileNetworkRepository.getSubInfoById(
+ String.valueOf(mSubId));
+ mMobileNetworkInfoEntity =
+ mMobileNetworkRepository.queryMobileNetworkInfoBySubId(
+ String.valueOf(mSubId));
+ });
+ if (mSubId <= SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
return Arrays.asList();
}
return Arrays.asList(
new DataUsageSummaryPreferenceController(getActivity(), getSettingsLifecycle(),
+ this, mSubId),
+ new RoamingPreferenceController(context, KEY_ROAMING_PREF, getSettingsLifecycle(),
this, mSubId));
}
@@ -151,28 +176,38 @@
public void onAttach(Context context) {
super.onAttach(context);
- Intent intent = getIntent();
- SubscriptionInfo info = SubscriptionUtil.getSubscriptionOrDefault(context, mSubId);
- if (info == null) {
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
Log.d(LOG_TAG, "Invalid subId request " + mSubId);
return;
}
- int oldSubId = mSubId;
- updateSubscriptions(info);
- // If the subscription has changed or the new intent does not contain the opt in action,
- // remove the old discovery dialog. If the activity is being recreated, we will see
- // onCreate -> onNewIntent, so the dialog will first be recreated for the old subscription
- // and then removed.
- if (!MobileNetworkActivity.doesIntentContainOptInAction(intent)) {
- removeContactDiscoveryDialog(oldSubId);
- }
+ Intent intent = getIntent();
+ if (intent != null) {
+ int updateSubscriptionIndex = intent.getIntExtra(Settings.EXTRA_SUB_ID,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- // evaluate showing the new discovery dialog if this intent contains an action to show the
- // opt-in.
- if (MobileNetworkActivity.doesIntentContainOptInAction(intent)) {
- showContactDiscoveryDialog(
- SubscriptionUtil.getSubscriptionOrDefault(context, mSubId));
+ if (updateSubscriptionIndex != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ int oldSubId = mSubId;
+ mSubId = updateSubscriptionIndex;
+ // If the subscription has changed or the new intent does not contain the opt in
+ // action,
+ // remove the old discovery dialog. If the activity is being recreated, we will see
+ // onCreate -> onNewIntent, so the dialog will first be recreated for the old
+ // subscription
+ // and then removed.
+ if (updateSubscriptionIndex != oldSubId
+ || !MobileNetworkActivity.doesIntentContainOptInAction(intent)) {
+ removeContactDiscoveryDialog(oldSubId);
+ }
+
+ // evaluate showing the new discovery dialog if this intent contains an action to
+ // show the
+ // opt-in.
+ if (MobileNetworkActivity.doesIntentContainOptInAction(intent)) {
+ showContactDiscoveryDialog();
+ }
+ }
+
}
final DataUsageSummaryPreferenceController dataUsageSummaryPreferenceController =
@@ -194,7 +229,13 @@
use(MobileDataPreferenceController.class).setWifiPickerTrackerHelper(
new WifiPickerTrackerHelper(getSettingsLifecycle(), context,
null /* WifiPickerTrackerCallback */));
- use(RoamingPreferenceController.class).init(getFragmentManager(), mSubId);
+
+ final RoamingPreferenceController roamingPreferenceController =
+ use(RoamingPreferenceController.class);
+ if (roamingPreferenceController != null) {
+ roamingPreferenceController.init(getFragmentManager(), mSubId,
+ mMobileNetworkInfoEntity);
+ }
use(ApnPreferenceController.class).init(mSubId);
use(CarrierPreferenceController.class).init(mSubId);
use(DataUsagePreferenceController.class).init(mSubId);
@@ -258,68 +299,36 @@
@Override
public void onResume() {
super.onResume();
+ mMobileNetworkRepository.addRegister(this);
// TODO: remove log after fixing b/182326102
Log.d(LOG_TAG, "onResume() subId=" + mSubId);
- if (mActiveSubscriptionsListener == null) {
- mActiveSubscriptionsListener = new ActiveSubscriptionsListener(
- getContext().getMainLooper(), getContext(), mSubId) {
- public void onChanged() {
- onSubscriptionDetailChanged();
- }
- };
- mDropFirstSubscriptionChangeNotify = true;
- }
- mActiveSubscriptionsListener.start();
}
private void onSubscriptionDetailChanged() {
- if (mDropFirstSubscriptionChangeNotify) {
- mDropFirstSubscriptionChangeNotify = false;
- Log.d(LOG_TAG, "Callback during onResume()");
- return;
- }
- final SubscriptionInfo subInfo = SubscriptionUtil
- .getSubscriptionOrDefault(getContext(), mSubId);
-
- if (subInfo != null) {
+ if (mSubscriptionInfoEntity != null) {
/**
* Update the title when SIM stats got changed
*/
final Consumer<Activity> renameTitle = activity -> {
if (activity != null && !activity.isFinishing()) {
if (activity instanceof SettingsActivity) {
- final CharSequence displayName = SubscriptionUtil
- .getUniqueSubscriptionDisplayName(subInfo, activity);
- ((SettingsActivity)activity).setTitle(displayName);
+ ((SettingsActivity) activity).setTitle(mSubscriptionInfoEntity.uniqueName);
}
}
};
- ThreadUtils.postOnMainThread(() -> renameTitle.accept(getActivity()));
+ ThreadUtils.postOnMainThread(() -> {
+ renameTitle.accept(getActivity());
+ redrawPreferenceControllers();
+ });
}
-
- mActiveSubscriptionsListenerCount++;
- if (mActiveSubscriptionsListenerCount != 1) {
- return;
- }
-
- ThreadUtils.postOnMainThread(() -> {
- if (subInfo == null) {
- finishFragment();
- return;
- }
- mActiveSubscriptionsListenerCount = 0;
- redrawPreferenceControllers();
- });
}
@Override
public void onDestroy() {
- if (mActiveSubscriptionsListener != null) {
- mActiveSubscriptionsListener.stop();
- }
super.onDestroy();
+ mMobileNetworkRepository.removeRegister();
}
@VisibleForTesting
@@ -375,7 +384,7 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
+ if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
final MenuItem item = menu.add(Menu.NONE, R.id.edit_sim_name, Menu.NONE,
R.string.mobile_network_sim_name);
item.setIcon(com.android.internal.R.drawable.ic_mode_edit);
@@ -386,7 +395,7 @@
@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
- if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
+ if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
if (menuItem.getItemId() == R.id.edit_sim_name) {
RenameMobileNetworkDialogFragment.newInstance(mSubId).show(
getFragmentManager(), RenameMobileNetworkDialogFragment.TAG);
@@ -422,18 +431,18 @@
}
}
- private void showContactDiscoveryDialog(SubscriptionInfo info) {
- if (info == null) {
- Log.d(LOG_TAG, "Invalid subId request " + mSubId);
+ private void showContactDiscoveryDialog() {
+ ContactDiscoveryDialogFragment fragment = getContactDiscoveryFragment(mSubId);
+
+ if (mSubscriptionInfoEntity == null) {
+ Log.d(LOG_TAG, "Zoey, showContactDiscoveryDialog, Invalid subId request " + mSubId);
onDestroy();
return;
}
- CharSequence carrierName = SubscriptionUtil.getUniqueSubscriptionDisplayName(info,
- getContext());
- ContactDiscoveryDialogFragment fragment = getContactDiscoveryFragment(mSubId);
if (fragment == null) {
- fragment = ContactDiscoveryDialogFragment.newInstance(mSubId, carrierName);
+ fragment = ContactDiscoveryDialogFragment.newInstance(mSubId,
+ mSubscriptionInfoEntity.uniqueName);
}
// Only try to show the dialog if it has not already been added, otherwise we may
// accidentally add it multiple times, causing multiple dialogs.
@@ -443,12 +452,53 @@
}
}
- private void updateSubscriptions(SubscriptionInfo subscription) {
- if (subscription == null) {
- return;
- }
- final int subscriptionIndex = subscription.getSubscriptionId();
+ @Override
+ public void onAvailableSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
+ }
- mSubId = subscriptionIndex;
+ @Override
+ public void onActiveSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
+ if (DataServiceUtils.shouldUpdateEntityList(mSubInfoEntityList, subInfoEntityList)) {
+
+ // Check the current subId is existed or not, if so, finish it.
+ if (!mSubscriptionInfoMap.isEmpty()) {
+
+ // Check each subInfo and remove it in the map based on the new list.
+ for (SubscriptionInfoEntity entity : subInfoEntityList) {
+ mSubscriptionInfoMap.remove(Integer.parseInt(entity.subId));
+ }
+
+ Iterator<Integer> iterator = mSubscriptionInfoMap.keySet().iterator();
+ while (iterator.hasNext()) {
+ if (iterator.next() == mSubId) {
+ finishFragment();
+ return;
+ }
+ }
+ }
+
+ mSubInfoEntityList = subInfoEntityList;
+ mSubInfoEntityList.forEach(entity -> {
+ int subId = Integer.parseInt(entity.subId);
+ mSubscriptionInfoMap.put(subId, entity);
+ if (subId == mSubId) {
+ mSubscriptionInfoEntity = entity;
+ onSubscriptionDetailChanged();
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onAllUiccInfoChanged(List<UiccInfoEntity> uiccInfoEntityList) {
+ }
+
+ @Override
+ public void onAllMobileNetworkInfoChanged(
+ List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList) {
+ }
+
+ @Override
+ public void onAirplaneModeChanged(boolean enabled) {
}
}
diff --git a/src/com/android/settings/network/telephony/RoamingPreferenceController.java b/src/com/android/settings/network/telephony/RoamingPreferenceController.java
index eb77312..2ed7d79 100644
--- a/src/com/android/settings/network/telephony/RoamingPreferenceController.java
+++ b/src/com/android/settings/network/telephony/RoamingPreferenceController.java
@@ -16,6 +16,9 @@
package com.android.settings.network.telephony;
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
import android.content.Context;
import android.os.PersistableBundle;
import android.provider.Settings;
@@ -25,21 +28,31 @@
import android.util.Log;
import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.network.GlobalSettingsChangeListener;
+import com.android.settings.network.MobileNetworkRepository;
import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.mobile.dataservice.DataServiceUtils;
+import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
+import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
+import com.android.settingslib.mobile.dataservice.UiccInfoEntity;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* Preference controller for "Roaming"
*/
public class RoamingPreferenceController extends TelephonyTogglePreferenceController implements
- LifecycleObserver, OnStart, OnStop {
+ LifecycleObserver, MobileNetworkRepository.MobileNetworkCallback {
private static final String TAG = "RoamingController";
private static final String DIALOG_TAG = "MobileDataDialog";
@@ -47,6 +60,9 @@
private RestrictedSwitchPreference mSwitchPreference;
private TelephonyManager mTelephonyManager;
private CarrierConfigManager mCarrierConfigManager;
+ protected MobileNetworkRepository mMobileNetworkRepository;
+ protected LifecycleOwner mLifecycleOwner;
+ private List<MobileNetworkInfoEntity> mMobileNetworkInfoEntityList = new ArrayList<>();
/**
* There're 2 listeners both activated at the same time.
@@ -59,10 +75,18 @@
@VisibleForTesting
FragmentManager mFragmentManager;
+ MobileNetworkInfoEntity mMobileNetworkInfoEntity;
- public RoamingPreferenceController(Context context, String key) {
+ public RoamingPreferenceController(Context context, String key, Lifecycle lifecycle,
+ LifecycleOwner lifecycleOwner, int subId) {
super(context, key);
+ mSubId = subId;
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
+ mMobileNetworkRepository = MobileNetworkRepository.createBySubId(context, this, mSubId);
+ mLifecycleOwner = lifecycleOwner;
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
}
@Override
@@ -75,8 +99,9 @@
return AVAILABLE;
}
- @Override
+ @OnLifecycleEvent(ON_START)
public void onStart() {
+ mMobileNetworkRepository.addRegister(mLifecycleOwner);
if (mListener == null) {
mListener = new GlobalSettingsChangeListener(mContext,
Settings.Global.DATA_ROAMING) {
@@ -100,8 +125,9 @@
};
}
- @Override
+ @OnLifecycleEvent(ON_STOP)
public void onStop() {
+ mMobileNetworkRepository.removeRegister();
stopMonitor();
stopMonitorSubIdSpecific();
}
@@ -114,7 +140,7 @@
@Override
public int getAvailabilityStatus(int subId) {
- return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
? AVAILABLE
: AVAILABLE_UNSEARCHABLE;
}
@@ -135,19 +161,26 @@
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- final RestrictedSwitchPreference switchPreference = (RestrictedSwitchPreference) preference;
- if (!switchPreference.isDisabledByAdmin()) {
- switchPreference.setEnabled(mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- switchPreference.setChecked(isChecked());
+ mSwitchPreference = (RestrictedSwitchPreference) preference;
+ update();
+ }
+
+ private void update() {
+ if (mSwitchPreference == null) {
+ return;
+ }
+ if (!mSwitchPreference.isDisabledByAdmin()) {
+ mSwitchPreference.setEnabled(mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ mSwitchPreference.setChecked(isChecked());
}
}
@VisibleForTesting
boolean isDialogNeeded() {
- final boolean isRoamingEnabled = mTelephonyManager.isDataRoamingEnabled();
+ final boolean isRoamingEnabled = mMobileNetworkInfoEntity == null ? false
+ : mMobileNetworkInfoEntity.isDataRoamingEnabled;
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(
mSubId);
-
// Need dialog if we need to turn on roaming and the roaming charge indication is allowed
if (!isRoamingEnabled && (carrierConfig == null || !carrierConfig.getBoolean(
CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL))) {
@@ -158,12 +191,14 @@
@Override
public boolean isChecked() {
- return mTelephonyManager.isDataRoamingEnabled();
+ return mMobileNetworkInfoEntity == null ? false
+ : mMobileNetworkInfoEntity.isDataRoamingEnabled;
}
- public void init(FragmentManager fragmentManager, int subId) {
+ public void init(FragmentManager fragmentManager, int subId, MobileNetworkInfoEntity entity) {
mFragmentManager = fragmentManager;
mSubId = subId;
+ mMobileNetworkInfoEntity = entity;
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
return;
@@ -197,4 +232,42 @@
mListenerForSubId = null;
}
}
+
+ @VisibleForTesting
+ public void setMobileNetworkInfoEntity(MobileNetworkInfoEntity mobileNetworkInfoEntity) {
+ mMobileNetworkInfoEntity = mobileNetworkInfoEntity;
+ }
+
+ @Override
+ public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
+ }
+
+ @Override
+ public void onAvailableSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
+ }
+
+ @Override
+ public void onActiveSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
+ }
+
+ @Override
+ public void onAllUiccInfoChanged(List<UiccInfoEntity> uiccInfoEntityList) {
+ }
+
+ @Override
+ public void onAllMobileNetworkInfoChanged(
+ List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList) {
+ if (DataServiceUtils.shouldUpdateEntityList(mMobileNetworkInfoEntityList,
+ mobileNetworkInfoEntityList)) {
+ mMobileNetworkInfoEntityList = mobileNetworkInfoEntityList;
+ mMobileNetworkInfoEntityList.forEach(entity -> {
+ if (Integer.parseInt(entity.subId) == mSubId) {
+ mMobileNetworkInfoEntity = entity;
+ update();
+ refreshSummary(mSwitchPreference);
+ return;
+ }
+ });
+ }
+ }
}
diff --git a/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java
index 5dd4453..1b9103f 100644
--- a/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java
+++ b/src/com/android/settings/network/telephony/cdma/CdmaSystemSelectPreferenceController.java
@@ -18,6 +18,7 @@
import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA;
import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA;
+import static com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants.NETWORK_MODE_UNKNOWN;
import android.content.Context;
import android.provider.Settings;
@@ -43,7 +44,10 @@
super.updateState(preference);
final ListPreference listPreference = (ListPreference) preference;
listPreference.setVisible(getAvailabilityStatus() == AVAILABLE);
- final int mode = mTelephonyManager.getCdmaRoamingMode();
+ boolean hasTelephonyMgr = mTelephonyManager != null;
+ final int mode =
+ hasTelephonyMgr ? mTelephonyManager.getCdmaRoamingMode()
+ : TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT;
if (mode != TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT) {
if (mode == TelephonyManager.CDMA_ROAMING_MODE_HOME
|| mode == TelephonyManager.CDMA_ROAMING_MODE_ANY) {
@@ -53,9 +57,11 @@
}
}
- final int settingsNetworkMode = MobileNetworkUtils.getNetworkTypeFromRaf(
- (int) mTelephonyManager.getAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
+ final int settingsNetworkMode =
+ hasTelephonyMgr ? MobileNetworkUtils.getNetworkTypeFromRaf(
+ (int) mTelephonyManager.getAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER))
+ : NETWORK_MODE_UNKNOWN;
final boolean enableList = settingsNetworkMode != NETWORK_MODE_LTE_GSM_WCDMA
&& settingsNetworkMode != NETWORK_MODE_NR_LTE_GSM_WCDMA;
listPreference.setEnabled(enableList);
diff --git a/src/com/android/settings/security/MemtagHelper.java b/src/com/android/settings/security/MemtagHelper.java
index ecd6ea6..c891eb2 100644
--- a/src/com/android/settings/security/MemtagHelper.java
+++ b/src/com/android/settings/security/MemtagHelper.java
@@ -46,7 +46,7 @@
if (MemtagHelper.isForcedOff()) {
return BasePreferenceController.DISABLED_DEPENDENT_SETTING;
}
- return SystemProperties.getBoolean("ro.arm64.memtag.bootctl_supported", false)
+ return SystemProperties.getBoolean("ro.arm64.memtag.bootctl_settings_toggle", false)
? BasePreferenceController.AVAILABLE
: BasePreferenceController.UNSUPPORTED_ON_DEVICE;
}
diff --git a/src/com/android/settings/sim/smartForwarding/DisableSmartForwardingTask.java b/src/com/android/settings/sim/smartForwarding/DisableSmartForwardingTask.java
index d483dd1..a1035dc 100644
--- a/src/com/android/settings/sim/smartForwarding/DisableSmartForwardingTask.java
+++ b/src/com/android/settings/sim/smartForwarding/DisableSmartForwardingTask.java
@@ -57,10 +57,6 @@
}
private int getSubId(int slotIndex) {
- int[] subId = SubscriptionManager.getSubId(slotIndex);
- if (subId != null && subId.length > 0) {
- return subId[0];
- }
- return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ return SubscriptionManager.getSubscriptionId(slotIndex);
}
}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetailsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetailsPreferenceControllerTest.java
new file mode 100644
index 0000000..1b361d2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetailsPreferenceControllerTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.applications.appinfo;
+
+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.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+
+import androidx.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+
+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;
+
+@RunWith(RobolectricTestRunner.class)
+public class LongBackgroundTasksDetailsPreferenceControllerTest {
+
+ @Mock
+ private AppInfoDashboardFragment mFragment;
+ @Mock
+ private Preference mPreference;
+
+ private Context mContext;
+ private LongBackgroundTasksDetailsPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mController = spy(new LongBackgroundTasksDetailsPreferenceController(mContext, "test_key"));
+ mController.setPackageName("Package1");
+ mController.setParentFragment(mFragment);
+ final String key = mController.getPreferenceKey();
+ when(mPreference.getKey()).thenReturn(key);
+ }
+
+ @Test
+ public void getAvailabilityStatus_notCandidate_shouldReturnUnavailable() {
+ doReturn(false).when(mController).isCandidate();
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isCandidate_shouldReturnAvailable() {
+ doReturn(true).when(mController).isCandidate();
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getDetailFragmentClass_shouldReturnAlarmsAndRemindersDetails() {
+ assertThat(mController.getDetailFragmentClass())
+ .isEqualTo(LongBackgroundTasksDetails.class);
+ }
+
+ @Test
+ public void updateState_shouldSetSummary() {
+ final String summary = "test summary";
+ doReturn(summary).when(mController).getPreferenceSummary();
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setSummary(summary);
+ }
+
+ @Test
+ public void isCandidate_nullPackageInfo_shouldNotCrash() {
+ mController.isCandidate();
+ // no crash
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetailsTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetailsTest.java
new file mode 100644
index 0000000..7d159b9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/LongBackgroundTasksDetailsTest.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.applications.appinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+
+import com.android.settings.applications.AppStateLongBackgroundTasksBridge;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+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.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class LongBackgroundTasksDetailsTest {
+
+ @Mock
+ private RestrictedSwitchPreference mSwitchPref;
+ @Mock
+ private PackageInfo mPackageInfo;
+ @Mock
+ private AppStateLongBackgroundTasksBridge mAppStateBridge;
+ @Mock
+ private AppStateLongBackgroundTasksBridge.LongBackgroundTasksState mPermissionState;
+
+ private LongBackgroundTasksDetails mFragment = new LongBackgroundTasksDetails();
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ ReflectionHelpers.setField(mFragment, "mSwitchPref", mSwitchPref);
+ ReflectionHelpers.setField(mFragment, "mAppBridge", mAppStateBridge);
+ }
+
+ @Test
+ public void refreshUi_noPackageInfo_shouldReturnFalseAndNoCrash() {
+ mFragment.refreshUi();
+
+ assertThat(mFragment.refreshUi()).isFalse();
+ // should not crash
+ }
+
+ @Test
+ public void refreshUi_noApplicationInfo_shouldReturnFalseAndNoCrash() {
+ ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo);
+
+ mFragment.refreshUi();
+
+ assertThat(mFragment.refreshUi()).isFalse();
+ // should not crash
+ }
+
+ @Test
+ public void refreshUi_hasApplicationInfo_shouldReturnTrue() {
+ ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo);
+ mPackageInfo.applicationInfo = new ApplicationInfo();
+ when(mAppStateBridge.createPermissionState(nullable(String.class), anyInt()))
+ .thenReturn(mPermissionState);
+
+ mFragment.refreshUi();
+
+ assertThat(mFragment.refreshUi()).isTrue();
+ }
+
+ @Test
+ public void refreshUi_switchPreferenceEnabled() {
+ ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo);
+ mPackageInfo.applicationInfo = new ApplicationInfo();
+ when(mAppStateBridge.createPermissionState(nullable(String.class), anyInt()))
+ .thenReturn(mPermissionState);
+ when(mPermissionState.shouldBeVisible()).thenReturn(false);
+
+ mFragment.refreshUi();
+ verify(mSwitchPref).setEnabled(false);
+
+ when(mPermissionState.shouldBeVisible()).thenReturn(true);
+
+ mFragment.refreshUi();
+ verify(mSwitchPref).setEnabled(true);
+ }
+
+ @Test
+ public void refreshUi_switchPreferenceChecked() {
+ ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo);
+ mPackageInfo.applicationInfo = new ApplicationInfo();
+ when(mAppStateBridge.createPermissionState(nullable(String.class), anyInt()))
+ .thenReturn(mPermissionState);
+
+ when(mPermissionState.isAllowed()).thenReturn(true);
+ mFragment.refreshUi();
+ verify(mSwitchPref).setChecked(true);
+
+ when(mPermissionState.isAllowed()).thenReturn(false);
+ mFragment.refreshUi();
+ verify(mSwitchPref).setChecked(false);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
index 2e5cc02..a6c019b 100644
--- a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
@@ -22,13 +22,16 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
import android.content.Intent;
+import android.hardware.face.Face;
import android.hardware.face.FaceManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.settings.R;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
@@ -47,6 +50,9 @@
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowLockPatternUtils.class,
@@ -77,6 +83,34 @@
mActivity.mOverrideFaceManager = mFaceManager;
}
+ private void setFaceManagerToHave(int numEnrollments) {
+ List<Face> faces = new ArrayList<>();
+ for (int i = 0; i < numEnrollments; i++) {
+ faces.add(new Face("Face " + i /* name */, 1 /*faceId */, 1 /* deviceId */));
+ }
+ when(mFaceManager.getEnrolledFaces(anyInt())).thenReturn(faces);
+ }
+
+ @Test
+ public void intro_CheckCanEnroll() {
+ setFaceManagerToHave(0 /* numEnrollments */);
+ setupActivity(new Intent());
+ mController.create();
+ int result = mActivity.checkMaxEnrolled();
+
+ assertThat(result).isEqualTo(0);
+ }
+
+ @Test
+ public void intro_CheckMaxEnrolled() {
+ setFaceManagerToHave(1 /* numEnrollments */);
+ setupActivity(new Intent());
+ mController.create();
+ int result = mActivity.checkMaxEnrolled();
+
+ assertThat(result).isEqualTo(R.string.face_intro_error_max);
+ }
+
@Test
public void testOnCreate() {
setupActivity(new Intent());
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
index 289bfab..185af9e 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
@@ -31,13 +31,12 @@
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.mock;
-
import android.content.Context;
import android.content.res.ColorStateList;
@@ -188,6 +187,38 @@
}
@Test
+ public void fingerprintUdfpsOverlayEnrollment_PlaysAllAnimationsAssetsCorrectly() {
+ initializeActivityFor(TYPE_UDFPS_OPTICAL);
+
+ int totalEnrollSteps = 25;
+ int initStageSteps = -1, initStageRemaining = 0;
+
+ when(mSidecar.getEnrollmentSteps()).thenReturn(initStageSteps);
+ when(mSidecar.getEnrollmentRemaining()).thenReturn(initStageRemaining);
+
+ mActivity.onEnrollmentProgressChange(initStageSteps, initStageRemaining);
+
+ when(mSidecar.getEnrollmentSteps()).thenReturn(totalEnrollSteps);
+
+ for (int remaining = totalEnrollSteps; remaining > 0; remaining--) {
+ when(mSidecar.getEnrollmentRemaining()).thenReturn(remaining);
+ mActivity.onEnrollmentProgressChange(totalEnrollSteps, remaining);
+ }
+
+ List<Integer> expectedLottieAssetOrder = List.of(
+ R.raw.udfps_center_hint_lottie,
+ R.raw.udfps_tip_hint_lottie,
+ R.raw.udfps_left_edge_hint_lottie,
+ R.raw.udfps_right_edge_hint_lottie
+ );
+
+ ArgumentCaptor<Integer> lottieAssetCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mIllustrationLottie, times(4)).setAnimation(lottieAssetCaptor.capture());
+ List<Integer> observedLottieAssetOrder = lottieAssetCaptor.getAllValues();
+ assertThat(observedLottieAssetOrder).isEqualTo(expectedLottieAssetOrder);
+ }
+
+ @Test
public void fingerprintSfpsEnroll_PlaysAllAnimationsAssetsCorrectly() {
initializeActivityFor(TYPE_POWER_BUTTON);
@@ -354,4 +385,4 @@
return mContext;
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyCleanupJobServiceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyCleanupJobServiceTest.java
index 76a9b06..4c276ba 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyCleanupJobServiceTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyCleanupJobServiceTest.java
@@ -71,7 +71,8 @@
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- mJobScheduler = spy(new JobSchedulerImpl(IJobScheduler.Stub.asInterface(new Binder())));
+ mJobScheduler = spy(new JobSchedulerImpl(mContext,
+ IJobScheduler.Stub.asInterface(new Binder())));
when(mContext.getSystemService(JobScheduler.class)).thenReturn(mJobScheduler);
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyConfigJobServiceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyConfigJobServiceTest.java
index c6aaa32..3807be6 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyConfigJobServiceTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyConfigJobServiceTest.java
@@ -69,7 +69,8 @@
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- mJobScheduler = spy(new JobSchedulerImpl(IJobScheduler.Stub.asInterface(new Binder())));
+ mJobScheduler = spy(new JobSchedulerImpl(mContext,
+ IJobScheduler.Stub.asInterface(new Binder())));
when(mContext.getSystemService(JobScheduler.class)).thenReturn(mJobScheduler);
mJobService = spy(new AnomalyConfigJobService());
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java
index dd90dc8..faa3275 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java
@@ -113,7 +113,8 @@
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- mJobScheduler = spy(new JobSchedulerImpl(IJobScheduler.Stub.asInterface(new Binder())));
+ mJobScheduler = spy(new JobSchedulerImpl(mContext,
+ IJobScheduler.Stub.asInterface(new Binder())));
when(mContext.getSystemService(JobScheduler.class)).thenReturn(mJobScheduler);
mPolicy = new BatteryTipPolicy(mContext);
diff --git a/tests/unit/src/com/android/settings/applications/manageapplications/AppFilterRegistryTest.java b/tests/unit/src/com/android/settings/applications/manageapplications/AppFilterRegistryTest.java
index 13bc3db..ff5c0d8 100644
--- a/tests/unit/src/com/android/settings/applications/manageapplications/AppFilterRegistryTest.java
+++ b/tests/unit/src/com/android/settings/applications/manageapplications/AppFilterRegistryTest.java
@@ -26,10 +26,12 @@
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_USAGE_ACCESS;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_WITH_OVERLAY;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_WRITE_SETTINGS;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_LONG_BACKGROUND_TASKS;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_ALARMS_AND_REMINDERS;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_BATTERY_OPTIMIZATION;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_GAMES;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_HIGH_POWER;
+import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_LONG_BACKGROUND_TASKS;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_MAIN;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_MANAGE_SOURCES;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_MEDIA_MANAGEMENT_APPS;
@@ -77,5 +79,8 @@
assertThat(registry.getDefaultFilterType(LIST_TYPE_STORAGE)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_GAMES)).isEqualTo(FILTER_APPS_ALL);
+
+ assertThat(registry.getDefaultFilterType(LIST_TYPE_LONG_BACKGROUND_TASKS))
+ .isEqualTo(FILTER_LONG_BACKGROUND_TASKS);
}
}
diff --git a/tests/unit/src/com/android/settings/network/ResetNetworkRestrictionViewBuilderTest.java b/tests/unit/src/com/android/settings/network/ResetNetworkRestrictionViewBuilderTest.java
new file mode 100644
index 0000000..fba4928
--- /dev/null
+++ b/tests/unit/src/com/android/settings/network/ResetNetworkRestrictionViewBuilderTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.network;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.UserManager;
+import android.view.View;
+
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class ResetNetworkRestrictionViewBuilderTest {
+
+ @Mock
+ private Activity mActivity;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private View mView;
+ @Mock
+ private AlertDialog.Builder mAlertDialogBuilder;
+
+ private ResetNetworkRestrictionViewBuilder mBuilder;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ doReturn(mUserManager).when(mActivity).getSystemService(Context.USER_SERVICE);
+ }
+
+ @Test
+ public void build_getNull_whenNoRestriction() {
+ mBuilder = new ResetNetworkRestrictionViewBuilder(mActivity) {
+ @Override
+ protected boolean hasUserRestriction() { return false; }
+ @Override
+ protected EnforcedAdmin getEnforceAdminByRestriction() { return null; }
+ };
+
+ assertThat(mBuilder.build()).isNull();
+ }
+
+ @Test
+ public void build_getView_whenUserRestriction() {
+ mBuilder = new ResetNetworkRestrictionViewBuilder(mActivity) {
+ @Override
+ protected boolean hasUserRestriction() { return true; }
+ @Override
+ protected View operationNotAllow() { return mView; }
+ };
+
+ assertThat(mBuilder.build()).isNotNull();
+ }
+
+ @Test
+ public void build_getView_whenEnforceAdminRestriction() {
+ doReturn(mAlertDialogBuilder).when(mAlertDialogBuilder).setOnDismissListener(any());
+
+ String restriction = ResetNetworkRestrictionViewBuilder.mRestriction;
+ EnforcedAdmin admin = RestrictedLockUtils.EnforcedAdmin
+ .createDefaultEnforcedAdminWithRestriction(restriction);
+
+ mBuilder = new ResetNetworkRestrictionViewBuilder(mActivity) {
+ @Override
+ protected boolean hasUserRestriction() { return false; }
+ @Override
+ protected EnforcedAdmin getEnforceAdminByRestriction() { return admin; }
+ @Override
+ protected AlertDialog.Builder createRestrictDialogBuilder(EnforcedAdmin admin) {
+ return mAlertDialogBuilder;
+ }
+ @Override
+ protected View createEmptyView() { return mView; }
+ };
+
+ assertThat(mBuilder.build()).isNotNull();
+ }
+}
diff --git a/tests/unit/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
index 7ff95fb..d221280 100644
--- a/tests/unit/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
@@ -23,12 +23,14 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.os.Looper;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
@@ -36,12 +38,16 @@
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
import org.junit.Before;
import org.junit.Test;
@@ -65,15 +71,25 @@
private FragmentTransaction mFragmentTransaction;
@Mock
private CarrierConfigManager mCarrierConfigManager;
+ @Mock
+ private Lifecycle mLifecycle;
+ @Mock
+ private LifecycleOwner mLifecycleOwner;
+ private LifecycleRegistry mLifecycleRegistry;
private RoamingPreferenceController mController;
private RestrictedSwitchPreference mPreference;
private Context mContext;
+ private MobileNetworkInfoEntity mMobileNetworkInfoEntity;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
mContext = spy(ApplicationProvider.getApplicationContext());
doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
doReturn(mSubscriptionManager).when(mContext).getSystemService(
@@ -87,11 +103,21 @@
doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction();
mPreference = spy(new RestrictedSwitchPreference(mContext));
- mController = spy(new RoamingPreferenceController(mContext, "roaming"));
- mController.init(mFragmentManager, SUB_ID);
+ mController = spy(
+ new RoamingPreferenceController(mContext, "roaming", mLifecycle, mLifecycleOwner,
+ SUB_ID));
+ mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner);
+ when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
+ mController.init(mFragmentManager, SUB_ID, mMobileNetworkInfoEntity);
mPreference.setKey(mController.getPreferenceKey());
}
+ private MobileNetworkInfoEntity setupMobileNetworkInfoEntity(String subId,
+ boolean isDataRoaming) {
+ return new MobileNetworkInfoEntity(subId, false, false, true, false, false, false, false,
+ false, false, false, isDataRoaming);
+ }
+
@Test
public void getAvailabilityStatus_validSubId_returnAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(
@@ -100,9 +126,11 @@
@Test
public void getAvailabilityStatus_invalidSubId_returnUnsearchable() {
- mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ mMobileNetworkInfoEntity);
- assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ assertThat(mController.getAvailabilityStatus(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID)).isEqualTo(
BasePreferenceController.AVAILABLE_UNSEARCHABLE);
}
@@ -111,14 +139,16 @@
final PersistableBundle bundle = new PersistableBundle();
bundle.putBoolean(CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
- doReturn(false).when(mTelephonyManager).isDataRoamingEnabled();
+ mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false);
+ mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
assertThat(mController.isDialogNeeded()).isTrue();
}
@Test
public void isDialogNeeded_roamingEnabled_returnFalse() {
- doReturn(true).when(mTelephonyManager).isDataRoamingEnabled();
+ mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
+ mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
assertThat(mController.isDialogNeeded()).isFalse();
}
@@ -126,10 +156,10 @@
@Test
@UiThreadTest
public void setChecked_needDialog_showDialog() {
- doReturn(false).when(mTelephonyManager).isDataRoamingEnabled();
+ mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false);
+ mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
doReturn(null).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
-
mController.setChecked(true);
verify(mFragmentManager).beginTransaction();
@@ -137,7 +167,11 @@
@Test
public void updateState_invalidSubId_disabled() {
- mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(
+ String.valueOf(SubscriptionManager.INVALID_SUBSCRIPTION_ID), false);
+ mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
+ mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ mMobileNetworkInfoEntity);
mController.updateState(mPreference);
@@ -146,7 +180,8 @@
@Test
public void updateState_validSubId_enabled() {
- doReturn(true).when(mTelephonyManager).isDataRoamingEnabled();
+ mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
+ mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
mController.updateState(mPreference);
@@ -191,7 +226,7 @@
@Test
public void getAvailabilityStatus_forceHomeNetworkIsTrue_shouldReturnConditionallyAvailable() {
final PersistableBundle bundle = new PersistableBundle();
- bundle.putBoolean(CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL, false);
+ bundle.putBoolean(CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL, true);
doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);