Merge "Implement SFPS guided enrollment for T6" into tm-qpr-dev

This commit is contained in:
Grace Cheng
2022-09-01 00:47:41 +00:00
committed by Android (Google) Code Review
18 changed files with 727 additions and 67 deletions

View File

@@ -0,0 +1,66 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="300dp"
android:height="300dp"
android:viewportWidth="300"
android:viewportHeight="300">
<path
android:fillColor="#FF000000"
android:pathData="M272,300H28c-15.5,0 -28,-12.5 -28,-28V28C0,12.5 12.5,0 28,0h244c15.5,0 28,12.5 28,28v244C300,287.5 287.5,300 272,300z"/>
<path
android:pathData="M251.9,199c-26.1,-49.5 -62.4,-112.1 -101.7,-121.9c-3.3,-1.1 -6.8,-1.8 -10.2,-2.1h-0.3c-0.4,0 -0.9,-0.1 -1.3,-0.1c-6,-0.3 -11.9,0.7 -17.5,2.9h-0.1c-0.8,0.3 -1.6,0.7 -2.4,1c-18.6,8.4 -23,19.2 -23,19.2c-3.6,6.5 -5.9,13.5 -6.8,20.8c-4.5,32 27.6,100.6 52,143.7c3.1,0.3 6.2,0.4 9.4,0.4C194.9,263.1 233.7,236.9 251.9,199z"
android:fillColor="#AD674E"/>
<path
android:pathData="M175.9,132.6c-0.4,0.2 -0.9,0.4 -1.4,0.4c-0.5,0 -1,-0.1 -1.4,-0.3c-8.1,-4.3 -19.9,-3.3 -30.1,2.5c-10.2,5.8 -17.1,15.5 -17.5,24.6c0,0.4 -0.1,0.7 -0.3,1.1c-0.2,0.3 -0.4,0.6 -0.7,0.9c-0.3,0.3 -0.6,0.4 -1,0.6c-0.4,0.1 -0.7,0.2 -1.1,0.2c-0.4,0 -0.7,-0.1 -1.1,-0.3c-0.3,-0.2 -0.7,-0.4 -0.9,-0.7s-0.4,-0.6 -0.6,-1c-0.1,-0.4 -0.2,-0.7 -0.2,-1.1c0.6,-11.2 8.4,-22.5 20.4,-29.3c12,-6.8 25.7,-7.8 35.6,-2.6c0.3,0.2 0.6,0.4 0.9,0.7c0.2,0.3 0.4,0.6 0.5,1c0.1,0.4 0.2,0.7 0.1,1.1c0,0.4 -0.1,0.7 -0.3,1.1C176.8,132 176.4,132.4 175.9,132.6z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M170.3,184.2c-0.2,0.1 -0.5,0.2 -0.7,0.3c-8.4,2.1 -19.1,-6 -22.4,-14.1c-2.4,-6.1 -0.5,-11.6 5.1,-14.8c2.4,-1.4 5.2,-1.8 7.8,-1.3c2.7,0.5 5.1,1.9 6.8,4.1l3.8,4.6c1,1.3 2.5,2.1 4.2,2.4c1.6,0.2 3.3,-0.2 4.7,-1.1c1.4,-0.9 2.3,-2.4 2.7,-4c0.4,-1.6 0.1,-3.3 -0.7,-4.8l-0.5,-0.9c-0.2,-0.3 -0.3,-0.7 -0.4,-1.1c0,-0.4 0,-0.8 0.1,-1.1c0.1,-0.4 0.3,-0.7 0.5,-1s0.5,-0.5 0.9,-0.7c0.3,-0.2 0.7,-0.3 1.1,-0.4c0.4,0 0.8,0 1.1,0.1c0.4,0.1 0.7,0.3 1,0.5c0.3,0.2 0.6,0.5 0.7,0.8l0.5,0.9c1.5,2.7 2,5.9 1.3,8.9s-2.5,5.7 -5.1,7.4c-2.6,1.8 -5.7,2.5 -8.7,2.1c-3.1,-0.4 -5.9,-2 -7.8,-4.4l-3.8,-4.6c-0.9,-1.1 -2.1,-1.8 -3.4,-2c-1.3,-0.3 -2.8,0 -3.9,0.7c-3.1,1.8 -3.9,4.3 -2.6,7.7c2.4,6.2 10.8,11.8 15.6,10.6c0.7,-0.2 1.4,-0.1 2,0.2c0.6,0.3 1.1,0.8 1.4,1.5c0.2,0.6 0.3,1.4 0,2C171.3,183.3 170.9,183.9 170.3,184.2L170.3,184.2z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M146.2,190c-0.5,0.3 -1.1,0.4 -1.7,0.4c-0.6,0 -1.1,-0.3 -1.6,-0.6c-3,-2.6 -5.6,-5.6 -7.6,-9c-7.6,-13.4 -2.4,-30.2 11.8,-38.3c14.2,-8.1 31.3,-4 38.9,9.4c0.2,0.3 0.3,0.7 0.4,1.1c0,0.4 0,0.8 -0.1,1.1c-0.1,0.4 -0.3,0.7 -0.5,1c-0.2,0.3 -0.5,0.5 -0.9,0.7c-0.3,0.2 -0.7,0.3 -1.1,0.4c-0.4,0 -0.8,0 -1.1,-0.1c-0.4,-0.1 -0.7,-0.3 -1,-0.5c-0.3,-0.2 -0.5,-0.5 -0.7,-0.8c-6,-10.6 -19.7,-13.8 -31.1,-7.2c-11.4,6.5 -15.6,19.9 -9.6,30.5c1.7,2.8 3.8,5.2 6.2,7.4c0.6,0.5 1,1.2 1,1.9c0.1,0.8 -0.2,1.5 -0.6,2.1C146.8,189.5 146.5,189.8 146.2,190z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M177.8,196.2c-5.7,3.3 -12.3,4.7 -18.9,3.9c-0.8,-0.1 -1.4,-0.5 -1.9,-1.1c-0.5,-0.6 -0.7,-1.4 -0.6,-2.1c0.1,-0.8 0.5,-1.4 1.1,-1.9c0.6,-0.5 1.4,-0.7 2.1,-0.6c5.6,0.6 11.2,-0.7 16,-3.6c4.8,-2.9 8.5,-7.4 10.5,-12.6c0.1,-0.4 0.3,-0.7 0.6,-1c0.2,-0.3 0.6,-0.5 0.9,-0.7c0.3,-0.2 0.7,-0.3 1.1,-0.3c0.4,0 0.8,0 1.1,0.2c0.4,0.1 0.7,0.3 1,0.6c0.3,0.3 0.5,0.6 0.7,0.9c0.2,0.3 0.3,0.7 0.3,1.1c0,0.4 0,0.8 -0.2,1.1C189,187 184.1,192.7 177.8,196.2z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M121.5,136.4c-0.6,0.3 -1.2,0.4 -1.9,0.3c-0.6,-0.1 -1.2,-0.4 -1.7,-0.9c-0.4,-0.5 -0.7,-1.1 -0.8,-1.7c-0.1,-0.6 0.1,-1.3 0.5,-1.8c4,-5.9 9.3,-10.8 15.5,-14.3c6.2,-3.5 13.1,-5.6 20.2,-6.1c0.4,0 0.8,0 1.1,0.2c0.4,0.1 0.7,0.3 1,0.6c0.3,0.3 0.5,0.6 0.7,0.9c0.2,0.3 0.3,0.7 0.3,1.1s0,0.8 -0.2,1.1c-0.1,0.4 -0.3,0.7 -0.6,1c-0.2,0.3 -0.6,0.5 -0.9,0.7c-0.3,0.2 -0.7,0.3 -1.1,0.3c-6.2,0.4 -12.3,2.2 -17.7,5.3c-5.4,3.1 -10.1,7.4 -13.6,12.6C122.2,135.9 121.9,136.2 121.5,136.4z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M135.4,106.5c-1.1,0 -2.2,-0.6 -2.7,-1.7c-0.7,-1.5 -0.1,-3.3 1.4,-4c13.8,-6.6 25.7,-3.2 26.2,-3c1.6,0.5 2.5,2.1 2,3.7c-0.5,1.6 -2.1,2.5 -3.7,2c-0.1,0 -10.2,-2.8 -21.9,2.7C136.3,106.4 135.8,106.5 135.4,106.5z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M101.5,136.6c-0.3,0 -0.5,0 -0.8,-0.1c-1.6,-0.4 -2.5,-2.1 -2.1,-3.6c0.2,-0.6 4.1,-15.1 25.3,-27.2c1.4,-0.8 3.3,-0.3 4.1,1.1c0.8,1.4 0.3,3.3 -1.1,4.1c-18.8,10.7 -22.5,23.4 -22.5,23.5C104,135.8 102.8,136.6 101.5,136.6z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M102.7,111.3c-0.6,0 -1.2,-0.2 -1.7,-0.5c-1.4,-0.9 -1.7,-2.8 -0.8,-4.2c0.2,-0.3 5.7,-8.2 21.9,-16.4c6.6,-3.3 13.6,-5.3 21,-5.8c1.7,-0.1 3.1,1.1 3.2,2.8s-1.1,3.1 -2.8,3.2c-6.5,0.5 -12.8,2.3 -18.7,5.2c-14.6,7.4 -19.6,14.3 -19.6,14.4C104.7,110.8 103.7,111.3 102.7,111.3z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M137.4,219.7c-0.4,0 -0.8,-0.1 -1.2,-0.3c-0.3,-0.1 -7.2,-3.3 -14.8,-11.8c-1.1,-1.2 -1,-3.1 0.2,-4.2c1.2,-1.1 3.1,-1 4.2,0.2c6.8,7.6 12.7,10.3 12.8,10.3c1.5,0.7 2.2,2.4 1.5,4C139.6,219 138.5,219.7 137.4,219.7z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M118,201.4c-1,0 -1.9,-0.5 -2.5,-1.3c-1.4,-2.2 -2.8,-4.4 -4,-6.7c-12.5,-24.1 -7.9,-36.3 -7.7,-36.8c0.6,-1.5 2.4,-2.3 3.9,-1.7c1.5,0.6 2.3,2.3 1.7,3.9c-0.1,0.3 -3.6,10.7 7.4,31.8c1.1,2.1 2.3,4.2 3.6,6.2c0.9,1.4 0.5,3.2 -0.8,4.2C119.1,201.2 118.6,201.4 118,201.4z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M156.8,212.4C156.7,212.4 156.7,212.4 156.8,212.4c-0.5,0 -12.2,-0.2 -23.9,-12.4c-6.1,-6.4 -10.4,-14.4 -12.5,-23c-0.4,-1.6 0.6,-3.2 2.2,-3.6c1.6,-0.4 3.2,0.6 3.6,2.2c1.9,7.6 5.7,14.6 11.1,20.3c9.8,10.3 19.2,10.5 19.6,10.5c1.6,0 3,1.4 3,3S158.4,212.4 156.8,212.4z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M216,174.9c-0.1,0 -0.2,0 -0.3,0c-1.6,-0.2 -2.8,-1.7 -2.6,-3.3c0,-0.1 0.7,-6.7 -2.4,-16.2c-0.5,-1.6 0.4,-3.3 2,-3.8c1.6,-0.5 3.3,0.4 3.8,2c3.4,10.9 2.6,18.4 2.6,18.7C218.8,173.8 217.5,174.9 216,174.9z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M210.1,148.9c-1.1,0 -2.2,-0.6 -2.7,-1.7c-1.1,-2.2 -2.3,-4.3 -3.5,-6.3c-12.7,-20.4 -23.5,-22.6 -23.6,-22.6c-1.6,-0.3 -2.7,-1.8 -2.4,-3.5c0.3,-1.6 1.8,-2.7 3.4,-2.5c0.5,0.1 13.4,2.3 27.7,25.4c1.3,2.1 2.6,4.4 3.8,6.8c0.7,1.5 0.1,3.3 -1.4,4C211,148.8 210.6,148.9 210.1,148.9z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M199.8,187.8c-0.5,0 -1,-0.1 -1.5,-0.4c-1.4,-0.8 -1.9,-2.7 -1.1,-4.1c0.2,-0.3 4.8,-8.5 0.9,-22.2c-2.1,-7.5 -6.2,-14.4 -11.8,-19.8c-1.2,-1.2 -1.2,-3.1 0,-4.2s3.1,-1.2 4.2,0c6.3,6.2 10.9,14 13.3,22.5c4.6,16.3 -1.3,26.5 -1.5,26.9C201.8,187.3 200.8,187.8 199.8,187.8z"
android:fillColor="#D2E3FC"/>
<path
android:fillColor="#FF000000"
android:pathData="M248,228.2m-40,0a40,40 0,1 1,80 0a40,40 0,1 1,-80 0"/>
<path
android:pathData="M261.4,214.1l-18.3,18.3l-8.6,-8.5l-4.9,4.9l13.5,13.6l23.3,-23.4z"
android:fillColor="#669DF6"/>
<path
android:pathData="M150,260.1c-60.7,0 -110.1,-49.4 -110.1,-110.1C39.9,89.3 89.3,39.9 150,39.9S260.1,89.3 260.1,150c0,13.5 -2.5,26.5 -7,38.5c2,0.3 4,0.7 5.9,1.2c4.5,-12.4 7,-25.8 7,-39.8C266.1,86 214,33.9 150,33.9S33.9,86 33.9,150S86,266.1 150,266.1c23.2,0 44.8,-6.8 62.9,-18.6c-1,-1.8 -1.8,-3.6 -2.5,-5.5C193.1,253.4 172.3,260.1 150,260.1z"
android:fillColor="#669DF6"/>
<path
android:pathData="M248,271.2c-23.7,0 -43,-19.3 -43,-43s19.3,-43 43,-43s43,19.3 43,43S271.7,271.2 248,271.2zM248,191.2c-20.4,0 -37,16.6 -37,37s16.6,37 37,37s37,-16.6 37,-37S268.4,191.2 248,191.2z"
android:fillColor="#669DF6"/>
</vector>

View File

@@ -0,0 +1,71 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="300dp"
android:height="300dp"
android:viewportWidth="300"
android:viewportHeight="300">
<path
android:pathData="M272,300H28c-15.5,0 -28,-12.5 -28,-28V28C0,12.5 12.5,0 28,0h244c15.5,0 28,12.5 28,28v244C300,287.5 287.5,300 272,300z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M243.1,240.2l-11.4,-11.4l2.9,-2.9l8.6,8.6l18.4,-18.3l2.8,2.8L243.1,240.2z"
android:strokeWidth="3"
android:fillColor="#669DF6"
android:strokeColor="#669DF6"/>
<path
android:pathData="M251.9,199c-26.1,-49.5 -62.4,-112.1 -101.7,-121.9c-3.3,-1.1 -6.8,-1.8 -10.2,-2.1h-0.3c-0.4,0 -0.9,-0.1 -1.3,-0.1c-6,-0.3 -11.9,0.7 -17.5,2.9h-0.1c-0.8,0.3 -1.6,0.7 -2.4,1c-18.6,8.4 -23,19.2 -23,19.2c-3.6,6.5 -5.9,13.5 -6.8,20.8c-4.5,32 27.6,100.6 52,143.7c3.1,0.3 6.2,0.4 9.4,0.4C194.9,263.1 233.7,236.9 251.9,199z"
android:fillColor="#AD674E"/>
<path
android:pathData="M175.9,132.6c-0.4,0.2 -0.9,0.4 -1.4,0.4c-0.5,0 -1,-0.1 -1.4,-0.3c-8.1,-4.3 -19.9,-3.3 -30.1,2.5c-10.2,5.8 -17.1,15.5 -17.5,24.6c0,0.4 -0.1,0.7 -0.3,1.1c-0.2,0.3 -0.4,0.6 -0.7,0.9c-0.3,0.3 -0.6,0.4 -1,0.6c-0.4,0.1 -0.7,0.2 -1.1,0.2c-0.4,0 -0.7,-0.1 -1.1,-0.3c-0.3,-0.2 -0.7,-0.4 -0.9,-0.7s-0.4,-0.6 -0.6,-1c-0.1,-0.4 -0.2,-0.7 -0.2,-1.1c0.6,-11.2 8.4,-22.5 20.4,-29.3c12,-6.8 25.7,-7.8 35.6,-2.6c0.3,0.2 0.6,0.4 0.9,0.7c0.2,0.3 0.4,0.6 0.5,1c0.1,0.4 0.2,0.7 0.1,1.1c0,0.4 -0.1,0.7 -0.3,1.1C176.8,132 176.4,132.4 175.9,132.6z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M170.3,184.2c-0.2,0.1 -0.5,0.2 -0.7,0.3c-8.4,2.1 -19.1,-6 -22.4,-14.1c-2.4,-6.1 -0.5,-11.6 5.1,-14.8c2.4,-1.4 5.2,-1.8 7.8,-1.3c2.7,0.5 5.1,1.9 6.8,4.1l3.8,4.6c1,1.3 2.5,2.1 4.2,2.4c1.6,0.2 3.3,-0.2 4.7,-1.1c1.4,-0.9 2.3,-2.4 2.7,-4c0.4,-1.6 0.1,-3.3 -0.7,-4.8l-0.5,-0.9c-0.2,-0.3 -0.3,-0.7 -0.4,-1.1c0,-0.4 0,-0.8 0.1,-1.1c0.1,-0.4 0.3,-0.7 0.5,-1s0.5,-0.5 0.9,-0.7c0.3,-0.2 0.7,-0.3 1.1,-0.4c0.4,0 0.8,0 1.1,0.1c0.4,0.1 0.7,0.3 1,0.5c0.3,0.2 0.6,0.5 0.7,0.8l0.5,0.9c1.5,2.7 2,5.9 1.3,8.9s-2.5,5.7 -5.1,7.4c-2.6,1.8 -5.7,2.5 -8.7,2.1c-3.1,-0.4 -5.9,-2 -7.8,-4.4l-3.8,-4.6c-0.9,-1.1 -2.1,-1.8 -3.4,-2c-1.3,-0.3 -2.8,0 -3.9,0.7c-3.1,1.8 -3.9,4.3 -2.6,7.7c2.4,6.2 10.8,11.8 15.6,10.6c0.7,-0.2 1.4,-0.1 2,0.2c0.6,0.3 1.1,0.8 1.4,1.5c0.2,0.6 0.3,1.4 0,2C171.3,183.3 170.9,183.9 170.3,184.2L170.3,184.2z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M146.2,190c-0.5,0.3 -1.1,0.4 -1.7,0.4c-0.6,0 -1.1,-0.3 -1.6,-0.6c-3,-2.6 -5.6,-5.6 -7.6,-9c-7.6,-13.4 -2.4,-30.2 11.8,-38.3c14.2,-8.1 31.3,-4 38.9,9.4c0.2,0.3 0.3,0.7 0.4,1.1c0,0.4 0,0.8 -0.1,1.1c-0.1,0.4 -0.3,0.7 -0.5,1c-0.2,0.3 -0.5,0.5 -0.9,0.7c-0.3,0.2 -0.7,0.3 -1.1,0.4c-0.4,0 -0.8,0 -1.1,-0.1c-0.4,-0.1 -0.7,-0.3 -1,-0.5c-0.3,-0.2 -0.5,-0.5 -0.7,-0.8c-6,-10.6 -19.7,-13.8 -31.1,-7.2c-11.4,6.5 -15.6,19.9 -9.6,30.5c1.7,2.8 3.8,5.2 6.2,7.4c0.6,0.5 1,1.2 1,1.9c0.1,0.8 -0.2,1.5 -0.6,2.1C146.8,189.5 146.5,189.8 146.2,190z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M177.8,196.2c-5.7,3.3 -12.3,4.7 -18.9,3.9c-0.8,-0.1 -1.4,-0.5 -1.9,-1.1c-0.5,-0.6 -0.7,-1.4 -0.6,-2.1c0.1,-0.8 0.5,-1.4 1.1,-1.9c0.6,-0.5 1.4,-0.7 2.1,-0.6c5.6,0.6 11.2,-0.7 16,-3.6c4.8,-2.9 8.5,-7.4 10.5,-12.6c0.1,-0.4 0.3,-0.7 0.6,-1c0.2,-0.3 0.6,-0.5 0.9,-0.7c0.3,-0.2 0.7,-0.3 1.1,-0.3c0.4,0 0.8,0 1.1,0.2c0.4,0.1 0.7,0.3 1,0.6c0.3,0.3 0.5,0.6 0.7,0.9c0.2,0.3 0.3,0.7 0.3,1.1c0,0.4 0,0.8 -0.2,1.1C189,187 184.1,192.7 177.8,196.2z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M121.5,136.4c-0.6,0.3 -1.2,0.4 -1.9,0.3c-0.6,-0.1 -1.2,-0.4 -1.7,-0.9c-0.4,-0.5 -0.7,-1.1 -0.8,-1.7c-0.1,-0.6 0.1,-1.3 0.5,-1.8c4,-5.9 9.3,-10.8 15.5,-14.3c6.2,-3.5 13.1,-5.6 20.2,-6.1c0.4,0 0.8,0 1.1,0.2c0.4,0.1 0.7,0.3 1,0.6c0.3,0.3 0.5,0.6 0.7,0.9c0.2,0.3 0.3,0.7 0.3,1.1s0,0.8 -0.2,1.1c-0.1,0.4 -0.3,0.7 -0.6,1c-0.2,0.3 -0.6,0.5 -0.9,0.7c-0.3,0.2 -0.7,0.3 -1.1,0.3c-6.2,0.4 -12.3,2.2 -17.7,5.3c-5.4,3.1 -10.1,7.4 -13.6,12.6C122.2,135.9 121.9,136.2 121.5,136.4z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M135.4,106.5c-1.1,0 -2.2,-0.6 -2.7,-1.7c-0.7,-1.5 -0.1,-3.3 1.4,-4c13.8,-6.6 25.7,-3.2 26.2,-3c1.6,0.5 2.5,2.1 2,3.7c-0.5,1.6 -2.1,2.5 -3.7,2c-0.1,0 -10.2,-2.8 -21.9,2.7C136.3,106.4 135.8,106.5 135.4,106.5z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M101.5,136.6c-0.3,0 -0.5,0 -0.8,-0.1c-1.6,-0.4 -2.5,-2.1 -2.1,-3.6c0.2,-0.6 4.1,-15.1 25.3,-27.2c1.4,-0.8 3.3,-0.3 4.1,1.1c0.8,1.4 0.3,3.3 -1.1,4.1c-18.8,10.7 -22.5,23.4 -22.5,23.5C104,135.8 102.8,136.6 101.5,136.6z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M102.7,111.3c-0.6,0 -1.2,-0.2 -1.7,-0.5c-1.4,-0.9 -1.7,-2.8 -0.8,-4.2c0.2,-0.3 5.7,-8.2 21.9,-16.4c6.6,-3.3 13.6,-5.3 21,-5.8c1.7,-0.1 3.1,1.1 3.2,2.8s-1.1,3.1 -2.8,3.2c-6.5,0.5 -12.8,2.3 -18.7,5.2c-14.6,7.4 -19.6,14.3 -19.6,14.4C104.7,110.8 103.7,111.3 102.7,111.3z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M137.4,219.7c-0.4,0 -0.8,-0.1 -1.2,-0.3c-0.3,-0.1 -7.2,-3.3 -14.8,-11.8c-1.1,-1.2 -1,-3.1 0.2,-4.2c1.2,-1.1 3.1,-1 4.2,0.2c6.8,7.6 12.7,10.3 12.8,10.3c1.5,0.7 2.2,2.4 1.5,4C139.6,219 138.5,219.7 137.4,219.7z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M118,201.4c-1,0 -1.9,-0.5 -2.5,-1.3c-1.4,-2.2 -2.8,-4.4 -4,-6.7c-12.5,-24.1 -7.9,-36.3 -7.7,-36.8c0.6,-1.5 2.4,-2.3 3.9,-1.7c1.5,0.6 2.3,2.3 1.7,3.9c-0.1,0.3 -3.6,10.7 7.4,31.8c1.1,2.1 2.3,4.2 3.6,6.2c0.9,1.4 0.5,3.2 -0.8,4.2C119.1,201.2 118.6,201.4 118,201.4z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M156.8,212.4C156.8,212.4 156.7,212.4 156.8,212.4c-0.5,0 -12.2,-0.2 -23.9,-12.4c-6.1,-6.4 -10.4,-14.4 -12.5,-23c-0.4,-1.6 0.6,-3.2 2.2,-3.6c1.6,-0.4 3.2,0.6 3.6,2.2c1.9,7.6 5.7,14.6 11.1,20.3c9.8,10.3 19.2,10.5 19.6,10.5c1.6,0 3,1.4 3,3S158.4,212.4 156.8,212.4z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M216,174.9c-0.1,0 -0.2,0 -0.3,0c-1.6,-0.2 -2.8,-1.7 -2.6,-3.3c0,-0.1 0.7,-6.7 -2.4,-16.2c-0.5,-1.6 0.4,-3.3 2,-3.8c1.6,-0.5 3.3,0.4 3.8,2c3.4,10.9 2.6,18.4 2.6,18.7C218.8,173.8 217.5,174.9 216,174.9z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M210.1,148.9c-1.1,0 -2.2,-0.6 -2.7,-1.7c-1.1,-2.2 -2.3,-4.3 -3.5,-6.3c-12.7,-20.4 -23.5,-22.6 -23.6,-22.6c-1.6,-0.3 -2.7,-1.8 -2.4,-3.5c0.3,-1.6 1.8,-2.7 3.4,-2.5c0.5,0.1 13.4,2.3 27.7,25.4c1.3,2.1 2.6,4.4 3.8,6.8c0.7,1.5 0.1,3.3 -1.4,4C211,148.8 210.6,148.9 210.1,148.9z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M199.8,187.8c-0.5,0 -1,-0.1 -1.5,-0.4c-1.4,-0.8 -1.9,-2.7 -1.1,-4.1c0.2,-0.3 4.8,-8.5 0.9,-22.2c-2.1,-7.5 -6.2,-14.4 -11.8,-19.8c-1.2,-1.2 -1.2,-3.1 0,-4.2s3.1,-1.2 4.2,0c6.3,6.2 10.9,14 13.3,22.5c4.6,16.3 -1.3,26.5 -1.5,26.9C201.8,187.3 200.8,187.8 199.8,187.8z"
android:fillColor="#D2E3FC"/>
<path
android:pathData="M259.1,189.8c-0.1,0 -0.2,-0.1 -0.3,-0.1c0,0 -0.1,0 -0.1,0c-0.1,0 -0.2,-0.1 -0.3,-0.1c0,0 0,0 0,0c-0.3,-0.1 -0.7,-0.2 -1,-0.2c0,0 -0.1,0 -0.1,0c-0.1,0 -0.2,0 -0.3,-0.1c0,0 -0.1,0 -0.1,0c-0.2,0 -0.3,-0.1 -0.5,-0.1c0,0 -0.1,0 -0.1,0c-0.1,0 -0.2,0 -0.2,-0.1c-0.1,0 -0.1,0 -0.2,0c-0.1,0 -0.2,0 -0.2,0c-0.1,0 -0.1,0 -0.2,0c-0.1,0 -0.2,0 -0.2,0c-0.1,0 -0.3,0 -0.4,-0.1c-0.1,0 -0.1,0 -0.2,0c-0.1,0 -0.2,0 -0.2,0c-0.1,0 -0.1,0 -0.2,0c-0.1,0 -0.2,0 -0.2,0c-0.1,0 -0.1,0 -0.2,0c-0.1,0 -0.3,0 -0.4,-0.1c0,0 0,0 0,0l0,0c-1.7,-0.2 -3.4,-0.3 -5.1,-0.3c-22.1,0 -40,17.9 -40,40c0,4.8 0.9,9.5 2.4,13.8l0,0c0,0 0,0 0,0c0,0.1 0.1,0.3 0.1,0.4c0,0.1 0,0.1 0.1,0.2c0,0.1 0.1,0.2 0.1,0.3c0,0.1 0,0.1 0.1,0.2c0,0.1 0.1,0.2 0.1,0.3c0,0.1 0,0.1 0.1,0.2c0,0.1 0.1,0.2 0.1,0.3c0,0.1 0.1,0.1 0.1,0.2c0,0.1 0.1,0.1 0.1,0.2c0,0.1 0.1,0.1 0.1,0.2c0,0.1 0,0.1 0.1,0.2c0,0.1 0.1,0.2 0.1,0.2c0,0 0,0.1 0,0.1c0.1,0.3 0.3,0.6 0.4,0.9c0,0 0,0 0,0.1c0.1,0.1 0.1,0.2 0.2,0.3c0,0 0,0 0,0c0.2,0.4 0.5,0.9 0.7,1.3c6.8,12.3 20,20.7 35.1,20.7c22.1,0 40,-17.9 40,-40C288,210 275.8,194.6 259.1,189.8z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M212.2,246.1c-0.1,-0.1 -0.1,-0.2 -0.2,-0.3c0,0 0,0 0,-0.1c-0.1,-0.3 -0.3,-0.6 -0.4,-0.9c0,0 0,-0.1 0,-0.1c0,-0.1 -0.1,-0.2 -0.1,-0.2c0,-0.1 0,-0.1 -0.1,-0.2c0,-0.1 -0.1,-0.1 -0.1,-0.2c0,-0.1 -0.1,-0.1 -0.1,-0.2c0,-0.1 -0.1,-0.1 -0.1,-0.2c0,-0.1 -0.1,-0.2 -0.1,-0.3c0,-0.1 0,-0.1 -0.1,-0.2c0,-0.1 -0.1,-0.2 -0.1,-0.3c0,-0.1 0,-0.1 -0.1,-0.2c0,-0.1 -0.1,-0.2 -0.1,-0.3c0,-0.1 0,-0.1 -0.1,-0.2c-0.1,-0.1 -0.1,-0.3 -0.1,-0.4c0,0 0,0 0,0l0,0c-17.4,11.4 -38.1,18.1 -60.4,18.1c-60.7,0 -110.1,-49.4 -110.1,-110.1S89.3,39.9 150,39.9S260.1,89.3 260.1,150c0,13.5 -2.5,26.5 -7,38.5l0,0c0,0 0,0 0,0c0.1,0 0.3,0 0.4,0.1c0.1,0 0.1,0 0.2,0c0.1,0 0.2,0 0.2,0c0.1,0 0.1,0 0.2,0c0.1,0 0.2,0 0.2,0c0.1,0 0.1,0 0.2,0c0.1,0 0.3,0 0.4,0.1c0.1,0 0.2,0 0.2,0c0.1,0 0.1,0 0.2,0c0.1,0 0.2,0 0.2,0c0.1,0 0.1,0 0.2,0c0.1,0 0.2,0 0.2,0.1c0,0 0.1,0 0.1,0c0.2,0 0.3,0.1 0.5,0.1c0,0 0.1,0 0.1,0c0.1,0 0.2,0 0.3,0.1c0,0 0.1,0 0.1,0c0.3,0.1 0.7,0.2 1,0.2c0,0 0,0 0,0c0.1,0 0.2,0.1 0.3,0.1c0,0 0.1,0 0.1,0c0.1,0 0.2,0.1 0.3,0.1c0,0 0,0 0,0c4.5,-12.4 7,-25.8 7,-39.8C266.1,86 214,33.9 150,33.9S33.9,86 33.9,150S86,266.1 150,266.1c23.2,0 44.8,-6.8 62.9,-18.6c0,0 0,0 0,0C212.7,247.1 212.5,246.6 212.2,246.1C212.2,246.2 212.2,246.2 212.2,246.1z"
android:fillColor="#1A73E8"/>
<path
android:pathData="M248,271.2c-23.7,0 -43,-19.3 -43,-43s19.3,-43 43,-43s43,19.3 43,43S271.7,271.2 248,271.2zM248,191.2c-20.4,0 -37,16.6 -37,37s16.6,37 37,37s37,-16.6 37,-37S268.4,191.2 248,191.2z"
android:fillColor="#1A73E8"/>
<path
android:pathData="M243.1,242.4l-13.5,-13.6l5,-4.9l8.5,8.5l18.4,-18.3l4.9,4.9z"
android:fillColor="#1A73E8"/>
</vector>

View File

@@ -0,0 +1,87 @@
<?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
-->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="?attr/fingerprint_layout_theme">
<LinearLayout
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:clipToPadding="false"
android:clipChildren="false">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<!-- Animation res MUST be set in code -->
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/illustration_lottie"
android:layout_width="@dimen/fingerprint_progress_bar_max_size"
android:layout_height="@dimen/fingerprint_progress_bar_max_size"
android:layout_marginTop="@dimen/udfps_lottie_translate_y"
android:scaleType="centerInside"
android:visibility="gone"
app:lottie_autoPlay="true"
app:lottie_loop="true"
android:clipChildren="false"
android:clipToPadding="false"
app:lottie_speed=".85"
android:layout_marginVertical="24dp" />
<com.google.android.setupdesign.view.FillContentLayout
android:layout_width="@dimen/fingerprint_progress_bar_max_size"
android:layout_height="@dimen/fingerprint_progress_bar_max_size"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:layout_marginVertical="24dp">
<com.android.settings.widget.RingProgressBar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fingerprint_progress_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:minHeight="@dimen/fingerprint_progress_bar_min_size"
android:progress="0" />
</com.google.android.setupdesign.view.FillContentLayout>
<TextView
style="@style/TextAppearance.ErrorText"
android:id="@+id/error_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:accessibilityLiveRegion="polite"
android:gravity="center"
android:visibility="invisible"/>
</RelativeLayout>
</LinearLayout>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -0,0 +1,70 @@
<?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
-->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setup_wizard_layout"
style="?attr/fingerprint_layout_theme"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:clipToPadding="false"
android:clipChildren="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<com.google.android.setupdesign.view.FillContentLayout
android:layout_width="@dimen/sfps_enrollment_finished_icon_max_size"
android:layout_height="@dimen/sfps_enrollment_finished_icon_max_size"
android:layout_marginTop="24dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:gravity="center">
<ImageView
android:id="@+id/fingerprint_in_app_indicator"
style="@style/SudContentIllustration"
android:layout_width="@dimen/sfps_enrollment_finished_icon_max_size"
android:layout_height="@dimen/sfps_enrollment_finished_icon_max_size"
android:contentDescription="@android:string/fingerprint_icon_content_description"
android:importantForAccessibility="no"
android:src="@drawable/sfps_enroll_finish" />
</com.google.android.setupdesign.view.FillContentLayout>
<!-- Added to align elements with fingerprint_enroll_enrolling_base -->
<TextView
style="@style/TextAppearance.ErrorText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:visibility="invisible" />
</LinearLayout>
</LinearLayout>
</com.google.android.setupdesign.GlifLayout>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -50,6 +50,12 @@
<color name="biometric_enroll_intro_color_outline">#5e5e5e</color>
<color name="fingerprint_enrollment_finish_color_outline">#669df6</color>
<!-- Side fingerprint sensor enrollment animation colors -->
<color name="sfps_enrollment_fp_captured_color">#d2e3fc</color> <!-- Blue 100 -->
<color name="sfps_enrollment_fp_error_color">#fad2cf</color> <!-- Red 100 -->
<color name="sfps_enrollment_progress_bar_fill_color">#669df6</color> <!-- Blue 400 -->
<color name="sfps_enrollment_progress_bar_error_color">#ee675c</color> <!-- Red 400 -->
<!-- Material inverse ripple color, useful for inverted backgrounds. -->
<color name="ripple_material_inverse">@*android:color/ripple_material_light</color>

View File

@@ -21,6 +21,7 @@
<item name="fingerprint_enroll_find_sensor" type="layout">@layout/fingerprint_enroll_find_sensor_base</item>
<item name="fingerprint_enroll_enrolling" type="layout">@layout/fingerprint_enroll_enrolling_base</item>
<item name="fingerprint_enroll_finish" type="layout">@layout/fingerprint_enroll_finish_base</item>
<item name="sfps_enroll_finish" type="layout">@layout/sfps_enroll_finish_base</item>
<item name="choose_lock_pattern" type="layout">@layout/choose_lock_pattern_common</item>
</resources>

View File

@@ -201,6 +201,12 @@
<!-- Fingerprint enrollment color -->
<color name="fingerprint_enrollment_finish_color_outline">#1A73E8</color>
<!-- Side fingerprint sensor guided enrollment fill colors -->
<color name="sfps_enrollment_fp_captured_color">#d2e3fc</color> <!-- Blue 100 -->
<color name="sfps_enrollment_fp_error_color">#fad2cf</color> <!-- Red 100 -->
<color name="sfps_enrollment_progress_bar_fill_color">#1a73e8</color> <!-- Blue 600 -->
<color name="sfps_enrollment_progress_bar_error_color">#d93025</color> <!-- Red 600 -->
<!-- Material inverse ripple color, useful for inverted backgrounds. -->
<color name="ripple_material_inverse">@*android:color/ripple_material_dark</color>

View File

@@ -222,6 +222,7 @@
<dimen name="fingerprint_error_text_appear_distance">16dp</dimen>
<dimen name="fingerprint_error_text_disappear_distance">-8dp</dimen>
<dimen name="fingerprint_animation_size">88dp</dimen>
<dimen name="sfps_enrollment_finished_icon_max_size">295dp</dimen>
<dimen name="fingerprint_progress_bar_max_size">240dp</dimen>
<dimen name="fingerprint_progress_bar_min_size">120dp</dimen>
<dimen name="fingerprint_enrolling_content_margin_vertical">24dp</dimen>

View File

@@ -1149,15 +1149,23 @@
<string name="cancel_lock_screen_dialog_button_label">Cancel</string>
<!-- Introduction title shown in fingerprint enrollment dialog to locate the sensor [CHAR LIMIT=29] -->
<string name="security_settings_fingerprint_enroll_find_sensor_title">Touch the sensor</string>
<!-- Introduction title shown in fingerprint enrollment dialog to locate the sensor [CHAR LIMIT=60] -->
<!-- Introduction title shown in SFPS enrollment dialog to locate the sensor [CHAR LIMIT=60] -->
<string name="security_settings_sfps_enroll_find_sensor_title">Touch the power button without pressing it</string>
<!-- Introduction title shown in UDFPS enrollment dialog to locate the sensor [CHAR LIMIT=60] -->
<string name="security_settings_udfps_enroll_find_sensor_title">How to set up your fingerprint</string>
<!-- Message shown in fingerprint enrollment dialog to locate the sensor -->
<string name="security_settings_fingerprint_enroll_find_sensor_message">It\u2019s on the back of your phone. Use your index finger.</string>
<!-- Message shown in fingerprint enrollment dialog to locate the sensor [CHAR LIMIT=NONE]-->
<!-- Message shown in SFPS enrollment dialog to locate the sensor (tablet) [CHAR LIMIT=NONE]-->
<string name="security_settings_sfps_enroll_find_sensor_message" product="tablet">The fingerprint sensor is on the power button. Its the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen.</string>
<!-- Message shown in SFPS enrollment dialog to locate the sensor (device) [CHAR LIMIT=NONE]-->
<string name="security_settings_sfps_enroll_find_sensor_message" product="device">The fingerprint sensor is on the power button. Its the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen.</string>
<!-- Message shown in SFPS enrollment dialog to locate the sensor (default) [CHAR LIMIT=NONE]-->
<string name="security_settings_sfps_enroll_find_sensor_message" product="default">The fingerprint sensor is on the power button. Its the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen.</string>
<!-- Message shown in UDFPS enrollment dialog to locate the sensor [CHAR LIMIT=NONE]-->
<string name="security_settings_udfps_enroll_find_sensor_message">The fingerprint sensor is on your screen. You\u2019ll capture your fingerprint on the next screen.</string>
<!-- Button for starting fingerprint enrollment. [CHAR LIMIT=10]-->
<string name="security_settings_udfps_enroll_find_sensor_start_button">Start</string>
<!-- Message announced to a11y users during fingerprint enrollment to help them locate the sensor. [CHAR LIMIT=NONE] -->
<!-- Message announced to a11y users during UDFPS enrollment to help them locate the sensor. [CHAR LIMIT=NONE] -->
<string name="security_settings_udfps_enroll_a11y">Move your finger across the screen to find the sensor. Touch &amp; hold the fingerprint sensor.</string>
<!-- Content description of graphic that shows where the fingerprint of the device is [CHAR LIMIT=NONE] -->
<string name="security_settings_fingerprint_enroll_find_sensor_content_description">Illustration with device and fingerprint sensor location</string>
@@ -1173,8 +1181,10 @@
<string name="security_settings_fingerprint_enroll_start_title">Touch the sensor</string>
<!-- Message shown in fingerprint enrollment dialog to begin enrollment [CHAR LIMIT=NONE] -->
<string name="security_settings_fingerprint_enroll_start_message">Put your finger on the sensor and lift after you feel a vibration</string>
<!-- Message shown in fingerprint enrollment dialog to begin enrollment [CHAR LIMIT=NONE] -->
<!-- Message shown in UDFPS enrollment dialog to begin enrollment [CHAR LIMIT=NONE] -->
<string name="security_settings_udfps_enroll_start_message">Keep your fingerprint flat on the sensor until you feel a vibration</string>
<!-- Message shown in SFPS enrollment dialog to begin enrollment [CHAR LIMIT=NONE] -->
<string name="security_settings_sfps_enroll_start_message">Without pressing the button, keep your fingerprint on the sensor until you feel a vibration.\n\nMove your finger slightly each time. This helps capture more of your fingerprint.</string>
<!-- Title shown in fingerprint enrollment [CHAR LIMIT=NONE]-->
<string name="security_settings_fingerprint_enroll_udfps_title">Touch &amp; hold the fingerprint sensor</string>
<!-- Title shown in fingerprint enrollment dialog to repeat touching the fingerprint sensor [CHAR LIMIT=40] -->
@@ -1193,14 +1203,28 @@
<string name="security_settings_udfps_enroll_left_edge_title">Place the left edge of your finger</string>
<!-- Title shown during fingerprint enrollment that instructs the user to enroll the right edge of their finger [CHAR LIMIT=80] -->
<string name="security_settings_udfps_enroll_right_edge_title">Place the right edge of your finger</string>
<!-- Title shown during SFPS enrollment that instructs the user to enroll the center of their finger [CHAR LIMIT=80] -->
<string name="security_settings_sfps_enroll_finger_center_title">Place the center part of your finger on the sensor</string>
<!-- Title shown during SFPS enrollment that instructs the user to enroll their fingertip [CHAR LIMIT=80] -->
<string name="security_settings_sfps_enroll_fingertip_title">Place the tip of your finger on the sensor</string>
<!-- Title shown during SFPS enrollment that instructs the user to enroll the left edge of their finger [CHAR LIMIT=80] -->
<string name="security_settings_sfps_enroll_left_edge_title">Place the left edge of your finger on the sensor</string>
<!-- Title shown during SFPS enrollment that instructs the user to enroll the right edge of their finger [CHAR LIMIT=80] -->
<string name="security_settings_sfps_enroll_right_edge_title">Finally, place the right edge of your finger on the sensor</string>
<!-- Message shown during fingerprint enrollment that instructs the user to enroll the edges of their finger [CHAR LIMIT=160] -->
<string name="security_settings_udfps_enroll_edge_message">Place the side of your fingerprint on the sensor and hold, then switch to the other side</string>
<!-- Message shown in fingerprint enrollment asking users to repeat touching the fingerprint sensor. [CHAR LIMIT=160] -->
<string name="security_settings_udfps_enroll_repeat_a11y_message">This helps capture more of your fingerprint</string>
<!-- Message read to a11y users when enrollment progress is made. The number is from 0 to 100. [CHAR LIMIT=NONE]-->
<!-- Message read to a11y users when SFPS enrollment progress is made. The number is from 0 to 100. [CHAR LIMIT=NONE]-->
<string name="security_settings_sfps_enroll_progress_a11y_message">Enrolling fingerprint <xliff:g id="percentage" example="10">%d</xliff:g> percent</string>
<!-- a11y label on finger animation indicating SFPS enrollment progress. The number is from 0 to 100. [CHAR LIMIT=NONE]-->
<string name="security_settings_sfps_animation_a11y_label">Enrolled <xliff:g id="percentage" example="10">%d</xliff:g> percent</string>
<!-- Message read to a11y users when UDFPS enrollment progress is made. The number is from 0 to 100. [CHAR LIMIT=NONE]-->
<string name="security_settings_udfps_enroll_progress_a11y_message">Enrolling fingerprint <xliff:g id="percentage" example="10">%d</xliff:g> percent</string>
<!-- Title shown in fingerprint enrollment dialog once enrollment is completed [CHAR LIMIT=29] -->
<string name="security_settings_fingerprint_enroll_finish_title">Fingerprint added</string>
<!-- Message shown in SFPS enrollment dialog once enrollment is completed [CHAR LIMIT=NONE] -->
<string name="security_settings_sfps_enroll_finish">Now you can use your fingerprint to unlock your tablet or verify it\u2019s you, like when you sign in to apps or approve a purchase</string>
<!-- Message shown in fingerprint enrollment dialog once enrollment is completed (tablet) [CHAR LIMIT=NONE] -->
<string name="security_settings_fingerprint_enroll_finish_v2_message" product="tablet">Now you can use your fingerprint to unlock your tablet or verify it\u2019s you, like when you sign in to apps</string>
<!-- Message shown in fingerprint enrollment dialog once enrollment is completed (device) [CHAR LIMIT=NONE] -->

View File

@@ -23,11 +23,16 @@ import android.animation.ObjectAnimator;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RawRes;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
@@ -65,6 +70,8 @@ import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.display.DisplayDensityUtils;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieProperty;
import com.airbnb.lottie.model.KeyPath;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -94,11 +101,33 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
private static final int STAGE_LEFT_EDGE = 3;
private static final int STAGE_RIGHT_EDGE = 4;
@VisibleForTesting
protected static final int SFPS_STAGE_NO_ANIMATION = 0;
@VisibleForTesting
protected static final int SFPS_STAGE_CENTER = 1;
@VisibleForTesting
protected static final int SFPS_STAGE_FINGERTIP = 2;
@VisibleForTesting
protected static final int SFPS_STAGE_LEFT_EDGE = 3;
@VisibleForTesting
protected static final int SFPS_STAGE_RIGHT_EDGE = 4;
@IntDef({STAGE_UNKNOWN, STAGE_CENTER, STAGE_GUIDED, STAGE_FINGERTIP, STAGE_LEFT_EDGE,
STAGE_RIGHT_EDGE})
@Retention(RetentionPolicy.SOURCE)
private @interface EnrollStage {}
@VisibleForTesting
@IntDef({STAGE_UNKNOWN, SFPS_STAGE_NO_ANIMATION, SFPS_STAGE_CENTER, SFPS_STAGE_FINGERTIP,
SFPS_STAGE_LEFT_EDGE, SFPS_STAGE_RIGHT_EDGE})
@Retention(RetentionPolicy.SOURCE)
protected @interface SfpsEnrollStage {}
/**
* If we don't see progress during this time, we show an error message to remind the users that
* they need to lift the finger and touch again.
@@ -123,10 +152,9 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
private FingerprintManager mFingerprintManager;
private boolean mCanAssumeUdfps;
private boolean mCanAssumeSidefps;
private boolean mCanAssumeSfps;
@Nullable private ProgressBar mProgressBar;
private ObjectAnimator mProgressAnim;
private TextView mDescriptionText;
private TextView mErrorText;
private Interpolator mFastOutSlowInInterpolator;
private Interpolator mLinearOutSlowInInterpolator;
@@ -146,6 +174,11 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
private boolean mHaveShownUdfpsTipLottie;
private boolean mHaveShownUdfpsLeftEdgeLottie;
private boolean mHaveShownUdfpsRightEdgeLottie;
private boolean mHaveShownSfpsNoAnimationLottie;
private boolean mHaveShownSfpsCenterLottie;
private boolean mHaveShownSfpsTipLottie;
private boolean mHaveShownSfpsLeftEdgeLottie;
private boolean mHaveShownSfpsRightEdgeLottie;
private boolean mShouldShowLottie;
private OrientationEventListener mOrientationEventListener;
@@ -188,7 +221,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
final List<FingerprintSensorPropertiesInternal> props =
mFingerprintManager.getSensorPropertiesInternal();
mCanAssumeUdfps = props != null && props.size() == 1 && props.get(0).isAnyUdfpsType();
mCanAssumeSidefps = props != null && props.size() == 1 && props.get(0).isAnySidefpsType();
mCanAssumeSfps = props != null && props.size() == 1 && props.get(0).isAnySidefpsType();
mAccessibilityManager = getSystemService(AccessibilityManager.class);
mIsAccessibilityEnabled = mAccessibilityManager.isEnabled();
@@ -226,13 +259,16 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
break;
}
setDescriptionText(R.string.security_settings_udfps_enroll_start_message);
} else if (mCanAssumeSfps) {
setContentView(R.layout.sfps_enroll_enrolling);
setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message);
} else {
setContentView(R.layout.fingerprint_enroll_enrolling);
setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message);
}
mIsSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
if (mCanAssumeUdfps) {
if (mCanAssumeUdfps || mCanAssumeSfps) {
updateTitleAndDescription();
} else {
setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
@@ -438,6 +474,9 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
if (mCanAssumeUdfps) {
updateTitleAndDescriptionForUdfps();
return;
} else if (mCanAssumeSfps) {
updateTitleAndDescriptionForSfps();
return;
}
if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) {
@@ -467,12 +506,10 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
setHeaderText(R.string.security_settings_udfps_enroll_fingertip_title);
if (!mHaveShownUdfpsTipLottie && mIllustrationLottie != null) {
mHaveShownUdfpsTipLottie = true;
setDescriptionText("");
mIllustrationLottie.setAnimation(R.raw.udfps_tip_hint_lottie);
mIllustrationLottie.setVisibility(View.VISIBLE);
mIllustrationLottie.playAnimation();
mIllustrationLottie.setContentDescription(
getString(R.string.security_settings_udfps_tip_fingerprint_help));
getString(R.string.security_settings_udfps_tip_fingerprint_help)
);
configureEnrollmentStage("", R.raw.udfps_tip_hint_lottie);
}
break;
@@ -480,12 +517,10 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
setHeaderText(R.string.security_settings_udfps_enroll_left_edge_title);
if (!mHaveShownUdfpsLeftEdgeLottie && mIllustrationLottie != null) {
mHaveShownUdfpsLeftEdgeLottie = true;
setDescriptionText("");
mIllustrationLottie.setAnimation(R.raw.udfps_left_edge_hint_lottie);
mIllustrationLottie.setVisibility(View.VISIBLE);
mIllustrationLottie.playAnimation();
mIllustrationLottie.setContentDescription(
getString(R.string.security_settings_udfps_side_fingerprint_help));
getString(R.string.security_settings_udfps_side_fingerprint_help)
);
configureEnrollmentStage("", R.raw.udfps_left_edge_hint_lottie);
} else if (mIllustrationLottie == null) {
if (isStageHalfCompleted()) {
setDescriptionText(
@@ -499,12 +534,11 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
setHeaderText(R.string.security_settings_udfps_enroll_right_edge_title);
if (!mHaveShownUdfpsRightEdgeLottie && mIllustrationLottie != null) {
mHaveShownUdfpsRightEdgeLottie = true;
setDescriptionText("");
mIllustrationLottie.setAnimation(R.raw.udfps_right_edge_hint_lottie);
mIllustrationLottie.setVisibility(View.VISIBLE);
mIllustrationLottie.playAnimation();
mIllustrationLottie.setContentDescription(
getString(R.string.security_settings_udfps_side_fingerprint_help));
getString(R.string.security_settings_udfps_side_fingerprint_help)
);
configureEnrollmentStage("", R.raw.udfps_right_edge_hint_lottie);
} else if (mIllustrationLottie == null) {
if (isStageHalfCompleted()) {
setDescriptionText(
@@ -529,9 +563,98 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
getLayout().getHeaderTextView().setContentDescription(description);
setTitle(description);
break;
}
}
// Interrupt any existing talkback speech to prevent stacking talkback messages
private void clearTalkback() {
AccessibilityManager.getInstance(getApplicationContext()).interrupt();
}
private void updateTitleAndDescriptionForSfps() {
if (mIsAccessibilityEnabled) {
clearTalkback();
getLayout().getDescriptionTextView().setAccessibilityLiveRegion(
View.ACCESSIBILITY_LIVE_REGION_POLITE);
}
switch (getCurrentSfpsStage()) {
case SFPS_STAGE_NO_ANIMATION:
setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
if (!mHaveShownSfpsNoAnimationLottie && mIllustrationLottie != null) {
mHaveShownSfpsNoAnimationLottie = true;
mIllustrationLottie.setContentDescription(
getString(
R.string.security_settings_sfps_animation_a11y_label,
0
)
);
configureEnrollmentStage(
getString(R.string.security_settings_sfps_enroll_start_message),
R.raw.sfps_lottie_no_animation
);
}
break;
case SFPS_STAGE_CENTER:
setHeaderText(R.string.security_settings_sfps_enroll_finger_center_title);
if (!mHaveShownSfpsCenterLottie && mIllustrationLottie != null) {
mHaveShownSfpsCenterLottie = true;
configureEnrollmentStage(
getString(R.string.security_settings_sfps_enroll_start_message),
R.raw.sfps_lottie_pad_center
);
}
break;
case SFPS_STAGE_FINGERTIP:
setHeaderText(R.string.security_settings_sfps_enroll_fingertip_title);
if (!mHaveShownSfpsTipLottie && mIllustrationLottie != null) {
mHaveShownSfpsTipLottie = true;
configureEnrollmentStage("", R.raw.sfps_lottie_tip);
}
break;
case SFPS_STAGE_LEFT_EDGE:
setHeaderText(R.string.security_settings_sfps_enroll_left_edge_title);
if (!mHaveShownSfpsLeftEdgeLottie && mIllustrationLottie != null) {
mHaveShownSfpsLeftEdgeLottie = true;
configureEnrollmentStage("", R.raw.sfps_lottie_left_edge);
}
break;
case SFPS_STAGE_RIGHT_EDGE:
setHeaderText(R.string.security_settings_sfps_enroll_right_edge_title);
if (!mHaveShownSfpsRightEdgeLottie && mIllustrationLottie != null) {
mHaveShownSfpsRightEdgeLottie = true;
configureEnrollmentStage("", R.raw.sfps_lottie_right_edge);
}
break;
case STAGE_UNKNOWN:
default:
// Don't use BiometricEnrollBase#setHeaderText, since that invokes setTitle,
// which gets announced for a11y upon entering the page. For SFPS, we want to
// announce a different string for a11y upon entering the page.
getLayout().setHeaderText(
R.string.security_settings_sfps_enroll_find_sensor_title);
setDescriptionText(R.string.security_settings_sfps_enroll_start_message);
final CharSequence description = getString(
R.string.security_settings_sfps_enroll_find_sensor_message);
getLayout().getHeaderTextView().setContentDescription(description);
setTitle(description);
break;
}
}
private void configureEnrollmentStage(CharSequence description, @RawRes int lottie) {
setDescriptionText(description);
mIllustrationLottie.setAnimation(lottie);
mIllustrationLottie.setVisibility(View.VISIBLE);
mIllustrationLottie.playAnimation();
}
@EnrollStage
private int getCurrentStage() {
if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) {
@@ -552,6 +675,26 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
}
@SfpsEnrollStage
private int getCurrentSfpsStage() {
if (mSidecar == null) {
return STAGE_UNKNOWN;
}
final int progressSteps = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining();
if (progressSteps < getStageThresholdSteps(0)) {
return SFPS_STAGE_NO_ANIMATION;
} else if (progressSteps < getStageThresholdSteps(1)) {
return SFPS_STAGE_CENTER;
} else if (progressSteps < getStageThresholdSteps(2)) {
return SFPS_STAGE_FINGERTIP;
} else if (progressSteps < getStageThresholdSteps(3)) {
return SFPS_STAGE_LEFT_EDGE;
} else {
return SFPS_STAGE_RIGHT_EDGE;
}
}
private boolean isStageHalfCompleted() {
// Prior to first enrollment step.
if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) {
@@ -574,7 +717,8 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
return true;
}
private int getStageThresholdSteps(int index) {
@VisibleForTesting
protected int getStageThresholdSteps(int index) {
if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) {
Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet");
return 1;
@@ -586,7 +730,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
@Override
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
if (!TextUtils.isEmpty(helpString)) {
if (!mCanAssumeUdfps) {
if (!(mCanAssumeUdfps || mCanAssumeSfps)) {
mErrorText.removeCallbacks(mTouchAgainRunnable);
}
showError(helpString);
@@ -598,27 +742,42 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
onCancelEnrollment(errMsgId);
}
private void announceEnrollmentProgress(CharSequence announcement) {
AccessibilityEvent e = AccessibilityEvent.obtain();
e.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
e.setClassName(getClass().getName());
e.setPackageName(getPackageName());
e.getText().add(announcement);
mAccessibilityManager.sendAccessibilityEvent(e);
}
@Override
public void onEnrollmentProgressChange(int steps, int remaining) {
updateProgress(true /* animate */);
final int percent = (int) (((float) (steps - remaining) / (float) steps) * 100);
if (mCanAssumeSfps) {
if (mIsAccessibilityEnabled) {
CharSequence announcement = getString(
R.string.security_settings_sfps_enroll_progress_a11y_message, percent);
announceEnrollmentProgress(announcement);
mIllustrationLottie.setContentDescription(
getString(
R.string.security_settings_sfps_animation_a11y_label,
percent)
);
}
}
updateTitleAndDescription();
animateFlash();
if (!mCanAssumeUdfps) {
if (mCanAssumeUdfps) {
if (mIsAccessibilityEnabled) {
CharSequence announcement = getString(
R.string.security_settings_udfps_enroll_progress_a11y_message, percent);
announceEnrollmentProgress(announcement);
}
} else if (!mCanAssumeSfps) {
mErrorText.removeCallbacks(mTouchAgainRunnable);
mErrorText.postDelayed(mTouchAgainRunnable, HINT_TIMEOUT_DURATION);
} else {
if (mIsAccessibilityEnabled) {
final int percent = (int) (((float)(steps - remaining) / (float) steps) * 100);
CharSequence cs = getString(
R.string.security_settings_udfps_enroll_progress_a11y_message, percent);
AccessibilityEvent e = AccessibilityEvent.obtain();
e.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
e.setClassName(getClass().getName());
e.setPackageName(getPackageName());
e.getText().add(cs);
mAccessibilityManager.sendAccessibilityEvent(e);
}
}
}
@@ -661,10 +820,13 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
private void showError(CharSequence error) {
if (mCanAssumeUdfps || mCanAssumeSidefps) {
if (mCanAssumeUdfps || mCanAssumeSfps) {
setHeaderText(error);
// Show nothing for subtitle when getting an error message.
setDescriptionText("");
if (mCanAssumeSfps) {
applySfpsErrorDynamicColors(getApplicationContext(), mIllustrationLottie, true);
}
} else {
mErrorText.setText(error);
if (mErrorText.getVisibility() == View.INVISIBLE) {
@@ -692,7 +854,10 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
private void clearError() {
if (!mCanAssumeUdfps && mErrorText.getVisibility() == View.VISIBLE) {
if (mCanAssumeSfps) {
applySfpsErrorDynamicColors(getApplicationContext(), mIllustrationLottie, false);
}
if ((!(mCanAssumeUdfps || mCanAssumeSfps)) && mErrorText.getVisibility() == View.VISIBLE) {
mErrorText.animate()
.alpha(0f)
.translationY(getResources().getDimensionPixelSize(
@@ -704,6 +869,44 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
}
/**
* Applies dynamic colors corresponding to showing or clearing errors on the progress bar
* and finger lottie for SFPS
*/
private void applySfpsErrorDynamicColors(Context context, LottieAnimationView composition,
boolean isError) {
applyProgressBarDynamicColor(context, isError);
applyLottieDynamicColor(context, composition, isError);
}
private void applyProgressBarDynamicColor(Context context, boolean isError) {
if (mProgressBar != null) {
int error_color = context.getColor(R.color.sfps_enrollment_progress_bar_error_color);
int progress_bar_fill_color = context.getColor(
R.color.sfps_enrollment_progress_bar_fill_color);
ColorStateList fillColor = ColorStateList.valueOf(
isError ? error_color : progress_bar_fill_color);
mProgressBar.setProgressTintList(fillColor);
mProgressBar.setProgressTintMode(PorterDuff.Mode.SRC_ATOP);
mProgressBar.invalidate();
}
}
private void applyLottieDynamicColor(Context context, LottieAnimationView composition,
boolean isError) {
if (composition != null) {
int error_color = context.getColor(R.color.sfps_enrollment_fp_error_color);
int fp_captured_color = context.getColor(R.color.sfps_enrollment_fp_captured_color);
int color = isError ? error_color : fp_captured_color;
composition.addValueCallback(
new KeyPath(".blue100", "**"),
LottieProperty.COLOR_FILTER,
frameInfo -> new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)
);
composition.invalidate();
}
}
private void listenOrientationEvent() {
mOrientationEventListener = new OrientationEventListener(this) {
@Override
@@ -803,20 +1006,24 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
private void updateOrientation(int orientation) {
switch(orientation) {
case Configuration.ORIENTATION_LANDSCAPE: {
mIllustrationLottie = null;
break;
}
case Configuration.ORIENTATION_PORTRAIT: {
if (mShouldShowLottie) {
mIllustrationLottie = findViewById(R.id.illustration_lottie);
if (mCanAssumeSfps && mShouldShowLottie) {
mIllustrationLottie = findViewById(R.id.illustration_lottie);
} else {
switch(orientation) {
case Configuration.ORIENTATION_LANDSCAPE: {
mIllustrationLottie = null;
break;
}
break;
case Configuration.ORIENTATION_PORTRAIT: {
if (mShouldShowLottie) {
mIllustrationLottie = findViewById(R.id.illustration_lottie);
}
break;
}
default:
Log.e(TAG, "Error unhandled configuration change");
break;
}
default:
Log.e(TAG, "Error unhandled configuration change");
break;
}
}
@@ -859,4 +1066,4 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
return SettingsEnums.DIALOG_FINGERPRINT_ICON_TOUCH;
}
}
}
}

View File

@@ -58,7 +58,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
private FingerprintEnrollSidecar mSidecar;
private boolean mNextClicked;
private boolean mCanAssumeUdfps;
private boolean mCanAssumeSidefps;
private boolean mCanAssumeSfps;
private OrientationEventListener mOrientationEventListener;
private int mPreviousRotation = 0;
@@ -71,7 +71,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
final List<FingerprintSensorPropertiesInternal> props =
fingerprintManager.getSensorPropertiesInternal();
mCanAssumeUdfps = props != null && props.size() == 1 && props.get(0).isAnyUdfpsType();
mCanAssumeSidefps = props != null && props.size() == 1 && props.get(0).isAnySidefpsType();
mCanAssumeSfps = props != null && props.size() == 1 && props.get(0).isAnySidefpsType();
setContentView(getContentView());
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
mFooterBarMixin.setSecondaryButton(
@@ -102,10 +102,9 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
if (am.isEnabled()) {
lottieAnimationView.setAnimation(R.raw.udfps_edu_a11y_lottie);
}
} else if (mCanAssumeSidefps) {
setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title);
setDescriptionText(R.string.security_settings_fingerprint_enroll_find_sensor_message);
} else if (mCanAssumeSfps) {
setHeaderText(R.string.security_settings_sfps_enroll_find_sensor_title);
setDescriptionText(R.string.security_settings_sfps_enroll_find_sensor_message);
final LottieAnimationView lottieAnimationView = findViewById(R.id.illustration_lottie);
final LottieAnimationView lottieAnimationViewPortrait =
findViewById(R.id.illustration_lottie_portrait);
@@ -201,7 +200,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
protected int getContentView() {
if (mCanAssumeUdfps) {
return R.layout.udfps_enroll_find_sensor_layout;
} else if (mCanAssumeSidefps) {
} else if (mCanAssumeSfps) {
return R.layout.sfps_enroll_find_sensor_layout;
}
return R.layout.fingerprint_enroll_find_sensor;
@@ -374,7 +373,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
}
private void listenOrientationEvent() {
if (!mCanAssumeSidefps) {
if (!mCanAssumeSfps) {
// Do nothing if the device doesn't support SideFPS.
return;
}
@@ -393,7 +392,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
}
private void stopListenOrientationEvent() {
if (!mCanAssumeSidefps) {
if (!mCanAssumeSfps) {
// Do nothing if the device doesn't support SideFPS.
return;
}

View File

@@ -49,15 +49,29 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase {
@VisibleForTesting
static final String FINGERPRINT_SUGGESTION_ACTIVITY =
"com.android.settings.SetupFingerprintSuggestionActivity";
private FingerprintManager mFingerprintManager;
private boolean mCanAssumeSfps;
private boolean mIsAddAnotherOrFinish;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fingerprint_enroll_finish);
mFingerprintManager = getSystemService(FingerprintManager.class);
final List<FingerprintSensorPropertiesInternal> props =
mFingerprintManager.getSensorPropertiesInternal();
mCanAssumeSfps = props != null && props.size() == 1 && props.get(0).isAnySidefpsType();
if (mCanAssumeSfps) {
setContentView(R.layout.sfps_enroll_finish);
} else {
setContentView(R.layout.fingerprint_enroll_finish);
}
setHeaderText(R.string.security_settings_fingerprint_enroll_finish_title);
setDescriptionText(R.string.security_settings_fingerprint_enroll_finish_v2_message);
if (mCanAssumeSfps) {
setDescriptionText(R.string.security_settings_sfps_enroll_finish);
} else {
setDescriptionText(R.string.security_settings_fingerprint_enroll_finish_v2_message);
}
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
mFooterBarMixin.setSecondaryButton(

View File

@@ -16,7 +16,11 @@
package com.android.settings.biometrics.fingerprint;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.KEY_STATE_PREVIOUS_ROTATION;
import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_NO_ANIMATION;
import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_RIGHT_EDGE;
import static com.google.common.truth.Truth.assertThat;
@@ -27,10 +31,12 @@ import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
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 android.content.Context;
import android.content.res.ColorStateList;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.SensorProperties;
import android.hardware.fingerprint.FingerprintManager;
@@ -46,6 +52,9 @@ import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.widget.RingProgressBar;
import com.airbnb.lottie.LottieAnimationView;
import org.junit.Before;
import org.junit.Ignore;
@@ -57,6 +66,7 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
@@ -68,8 +78,14 @@ public class FingerprintEnrollEnrollingTest {
@Mock private Vibrator mVibrator;
@Mock private LottieAnimationView mIllustrationLottie;
@Mock private FingerprintEnrollSidecar mSidecar;
@Mock private Display mMockDisplay;
private final int[] mSfpsStageThresholds = new int[]{0, 9, 13, 19, 25};
private FingerprintEnrollEnrolling mActivity;
private Context mContext;
@@ -130,6 +146,82 @@ public class FingerprintEnrollEnrollingTest {
verify(mActivity, never()).onCancelEnrollment(anyInt());
}
@Test
public void fingerprintSfpsEnroll_PlaysAllAnimationsAssetsCorrectly() {
initializeActivityFor(TYPE_POWER_BUTTON);
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.sfps_lottie_no_animation,
R.raw.sfps_lottie_pad_center,
R.raw.sfps_lottie_tip,
R.raw.sfps_lottie_left_edge,
R.raw.sfps_lottie_right_edge
);
ArgumentCaptor<Integer> lottieAssetCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mIllustrationLottie, times(5)).setAnimation(lottieAssetCaptor.capture());
List<Integer> observedLottieAssetOrder = lottieAssetCaptor.getAllValues();
assertThat(observedLottieAssetOrder).isEqualTo(expectedLottieAssetOrder);
}
// SFPS_STAGE_CENTER is first stage with progress bar colors, starts at steps=25, remaining=25
private void configureSfpsStageColorTest() {
when(mSidecar.getEnrollmentSteps()).thenReturn(25);
when(mSidecar.getEnrollmentRemaining()).thenReturn(25);
mActivity.onEnrollmentProgressChange(25, 25);
}
@Test
public void fingerprintSfpsEnroll_usesCorrectProgressBarFillColor() {
initializeActivityFor(TYPE_POWER_BUTTON);
configureSfpsStageColorTest();
int progress_bar_fill_color = mActivity.getApplicationContext().getColor(
R.color.sfps_enrollment_progress_bar_fill_color
);
RingProgressBar mProgressBar = mActivity.findViewById(R.id.fingerprint_progress_bar);
assertThat(mProgressBar.getProgressTintList()).isEqualTo(
ColorStateList.valueOf(progress_bar_fill_color)
);
}
@Test
public void fingerprintSfpsEnroll_usesCorrectProgressBarHelpColor() {
initializeActivityFor(TYPE_POWER_BUTTON);
configureSfpsStageColorTest();
int progress_bar_error_color = mActivity.getApplicationContext().getColor(
R.color.sfps_enrollment_progress_bar_error_color
);
mActivity.onEnrollmentHelp(
FingerprintManager.FINGERPRINT_ERROR_UNABLE_TO_PROCESS,
"test enrollment help"
);
RingProgressBar mProgressBar = mActivity.findViewById(R.id.fingerprint_progress_bar);
assertThat(mProgressBar.getProgressTintList()).isEqualTo(
ColorStateList.valueOf(progress_bar_error_color)
);
}
private void initializeActivityFor(int sensorType) {
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
final FingerprintSensorPropertiesInternal prop =
@@ -144,6 +236,7 @@ public class FingerprintEnrollEnrollingTest {
final Bundle savedInstanceState = new Bundle();
savedInstanceState.putInt(KEY_STATE_PREVIOUS_ROTATION, Surface.ROTATION_90);
props.add(prop);
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props);
mContext = spy(RuntimeEnvironment.application);
mActivity = spy(FingerprintEnrollEnrolling.class);
@@ -154,6 +247,16 @@ public class FingerprintEnrollEnrollingTest {
doReturn(true).when(mActivity).shouldShowLottie();
doReturn(mFingerprintManager).when(mActivity).getSystemService(FingerprintManager.class);
doReturn(mVibrator).when(mActivity).getSystemService(Vibrator.class);
doReturn(mIllustrationLottie).when(mActivity).findViewById(R.id.illustration_lottie);
ReflectionHelpers.setField(mActivity, "mSidecar", mSidecar);
if (sensorType == TYPE_POWER_BUTTON) {
// SFPS_STAGE_NO_ANIMATION = 0, ... , SFPS_STAGE_RIGHT_EDGE = 4
for (int stage = SFPS_STAGE_NO_ANIMATION; stage <= SFPS_STAGE_RIGHT_EDGE; stage++) {
doReturn(mSfpsStageThresholds[stage]).when(mActivity).getStageThresholdSteps(stage);
}
doReturn(true).when(mSidecar).isEnrolling();
}
ActivityController.of(mActivity).create(savedInstanceState);
}
@@ -171,4 +274,4 @@ public class FingerprintEnrollEnrollingTest {
return callbackCaptor.getValue();
}
}
}