Merge "Introduce bullet permission UI for singleDevice"

This commit is contained in:
Evan Chen
2022-11-22 05:13:11 +00:00
committed by Android (Google) Code Review
29 changed files with 645 additions and 79 deletions

View File

@@ -41,6 +41,7 @@ android_app {
"androidx.lifecycle_lifecycle-livedata",
"androidx.lifecycle_lifecycle-extensions",
"androidx.recyclerview_recyclerview",
"androidx-constraintlayout_constraintlayout",
"androidx.appcompat_appcompat",
],

View File

@@ -0,0 +1,25 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/system_accent1_200">
<path android:fillColor="@android:color/white"
android:pathData="M5,22Q4.175,22 3.587,21.413Q3,20.825 3,20V6Q3,5.175 3.587,4.588Q4.175,4 5,4H6V2H8V4H16V2H18V4H19Q19.825,4 20.413,4.588Q21,5.175 21,6V20Q21,20.825 20.413,21.413Q19.825,22 19,22ZM5,20H19Q19,20 19,20Q19,20 19,20V10H5V20Q5,20 5,20Q5,20 5,20Z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/system_accent1_200">
<path android:fillColor="@android:color/white"
android:pathData="M4,23V21H20V23ZM4,3V1H20V3ZM12,13Q13.25,13 14.125,12.125Q15,11.25 15,10Q15,8.75 14.125,7.875Q13.25,7 12,7Q10.75,7 9.875,7.875Q9,8.75 9,10Q9,11.25 9.875,12.125Q10.75,13 12,13ZM4,20Q3.175,20 2.588,19.413Q2,18.825 2,18V6Q2,5.175 2.588,4.588Q3.175,4 4,4H20Q20.825,4 21.413,4.588Q22,5.175 22,6V18Q22,18.825 21.413,19.413Q20.825,20 20,20ZM5.75,18Q6.875,16.6 8.475,15.8Q10.075,15 12,15Q13.925,15 15.525,15.8Q17.125,16.6 18.25,18H20Q20,18 20,18Q20,18 20,18V6Q20,6 20,6Q20,6 20,6H4Q4,6 4,6Q4,6 4,6V18Q4,18 4,18Q4,18 4,18ZM8.7,18H15.3Q14.575,17.5 13.738,17.25Q12.9,17 12,17Q11.1,17 10.263,17.25Q9.425,17.5 8.7,18ZM12,11Q11.575,11 11.288,10.712Q11,10.425 11,10Q11,9.575 11.288,9.287Q11.575,9 12,9Q12.425,9 12.713,9.287Q13,9.575 13,10Q13,10.425 12.713,10.712Q12.425,11 12,11ZM12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path android:fillColor="@android:color/system_accent1_200"
android:pathData="M12,16.4 L7.6,12 12,7.6 16.4,12ZM13.4,21.375Q13.125,21.65 12.75,21.8Q12.375,21.95 12,21.95Q11.625,21.95 11.25,21.8Q10.875,21.65 10.6,21.375L2.625,13.4Q2.35,13.125 2.2,12.75Q2.05,12.375 2.05,12Q2.05,11.625 2.2,11.25Q2.35,10.875 2.625,10.6L10.575,2.65Q10.875,2.35 11.238,2.2Q11.6,2.05 12,2.05Q12.4,2.05 12.762,2.2Q13.125,2.35 13.425,2.65L21.375,10.6Q21.65,10.875 21.8,11.25Q21.95,11.625 21.95,12Q21.95,12.375 21.8,12.75Q21.65,13.125 21.375,13.4ZM12,19.2 L19.2,12Q19.2,12 19.2,12Q19.2,12 19.2,12L12,4.8Q12,4.8 12,4.8Q12,4.8 12,4.8L4.8,12Q4.8,12 4.8,12Q4.8,12 4.8,12L12,19.2Q12,19.2 12,19.2Q12,19.2 12,19.2Z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/system_accent1_200">
<path android:fillColor="@android:color/white"
android:pathData="M19.95,21Q16.725,21 13.663,19.562Q10.6,18.125 8.238,15.762Q5.875,13.4 4.438,10.337Q3,7.275 3,4.05Q3,3.6 3.3,3.3Q3.6,3 4.05,3H8.1Q8.45,3 8.725,3.225Q9,3.45 9.05,3.8L9.7,7.3Q9.75,7.65 9.688,7.937Q9.625,8.225 9.4,8.45L7,10.9Q8.05,12.7 9.625,14.275Q11.2,15.85 13.1,17L15.45,14.65Q15.675,14.425 16.038,14.312Q16.4,14.2 16.75,14.25L20.2,14.95Q20.55,15.025 20.775,15.287Q21,15.55 21,15.9V19.95Q21,20.4 20.7,20.7Q20.4,21 19.95,21Z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/system_accent1_200">
<path android:fillColor="@android:color/white"
android:pathData="M8,11Q8.425,11 8.713,10.712Q9,10.425 9,10Q9,9.575 8.713,9.287Q8.425,9 8,9Q7.575,9 7.287,9.287Q7,9.575 7,10Q7,10.425 7.287,10.712Q7.575,11 8,11ZM12,11Q12.425,11 12.713,10.712Q13,10.425 13,10Q13,9.575 12.713,9.287Q12.425,9 12,9Q11.575,9 11.288,9.287Q11,9.575 11,10Q11,10.425 11.288,10.712Q11.575,11 12,11ZM16,11Q16.425,11 16.712,10.712Q17,10.425 17,10Q17,9.575 16.712,9.287Q16.425,9 16,9Q15.575,9 15.288,9.287Q15,9.575 15,10Q15,10.425 15.288,10.712Q15.575,11 16,11ZM2,22V4Q2,3.175 2.588,2.587Q3.175,2 4,2H20Q20.825,2 21.413,2.587Q22,3.175 22,4V16Q22,16.825 21.413,17.413Q20.825,18 20,18H6ZM4,16H20Q20,16 20,16Q20,16 20,16V4Q20,4 20,4Q20,4 20,4H4Q4,4 4,4Q4,4 4,4V16ZM4,16V4Q4,4 4,4Q4,4 4,4Q4,4 4,4Q4,4 4,4V16Q4,16 4,16Q4,16 4,16Z"/>
</vector>

View File

@@ -0,0 +1,24 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/system_neutral1_500">
<path android:fillColor="@android:color/white" android:pathData="M7.4,15.05 L6.35,13.975 12,8.325 17.65,13.975 16.6,15.05 12,10.45Z"/>
</vector>

View File

@@ -0,0 +1,24 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/system_neutral1_500">
<path android:fillColor="@android:color/white" android:pathData="M12,15.05 L6.35,9.375 7.4,8.325 12,12.925 16.6,8.325 17.65,9.375Z"/>
</vector>

View File

@@ -15,7 +15,8 @@
~ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:height="24dp"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">

View File

@@ -0,0 +1,24 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/system_accent1_600">
<path android:fillColor="@android:color/white" android:pathData="M5,22Q4.175,22 3.587,21.413Q3,20.825 3,20V6Q3,5.175 3.587,4.588Q4.175,4 5,4H6V2H8V4H16V2H18V4H19Q19.825,4 20.413,4.588Q21,5.175 21,6V20Q21,20.825 20.413,21.413Q19.825,22 19,22ZM5,20H19Q19,20 19,20Q19,20 19,20V10H5V20Q5,20 5,20Q5,20 5,20Z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/system_accent1_600">
<path android:fillColor="@android:color/white"
android:pathData="M4,23V21H20V23ZM4,3V1H20V3ZM12,13Q13.25,13 14.125,12.125Q15,11.25 15,10Q15,8.75 14.125,7.875Q13.25,7 12,7Q10.75,7 9.875,7.875Q9,8.75 9,10Q9,11.25 9.875,12.125Q10.75,13 12,13ZM4,20Q3.175,20 2.588,19.413Q2,18.825 2,18V6Q2,5.175 2.588,4.588Q3.175,4 4,4H20Q20.825,4 21.413,4.588Q22,5.175 22,6V18Q22,18.825 21.413,19.413Q20.825,20 20,20ZM5.75,18Q6.875,16.6 8.475,15.8Q10.075,15 12,15Q13.925,15 15.525,15.8Q17.125,16.6 18.25,18H20Q20,18 20,18Q20,18 20,18V6Q20,6 20,6Q20,6 20,6H4Q4,6 4,6Q4,6 4,6V18Q4,18 4,18Q4,18 4,18ZM8.7,18H15.3Q14.575,17.5 13.738,17.25Q12.9,17 12,17Q11.1,17 10.263,17.25Q9.425,17.5 8.7,18ZM12,11Q11.575,11 11.288,10.712Q11,10.425 11,10Q11,9.575 11.288,9.287Q11.575,9 12,9Q12.425,9 12.713,9.287Q13,9.575 13,10Q13,10.425 12.713,10.712Q12.425,11 12,11ZM12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path android:fillColor="@android:color/system_accent1_600"
android:pathData="M12,16.4 L7.6,12 12,7.6 16.4,12ZM13.4,21.375Q13.125,21.65 12.75,21.8Q12.375,21.95 12,21.95Q11.625,21.95 11.25,21.8Q10.875,21.65 10.6,21.375L2.625,13.4Q2.35,13.125 2.2,12.75Q2.05,12.375 2.05,12Q2.05,11.625 2.2,11.25Q2.35,10.875 2.625,10.6L10.575,2.65Q10.875,2.35 11.238,2.2Q11.6,2.05 12,2.05Q12.4,2.05 12.762,2.2Q13.125,2.35 13.425,2.65L21.375,10.6Q21.65,10.875 21.8,11.25Q21.95,11.625 21.95,12Q21.95,12.375 21.8,12.75Q21.65,13.125 21.375,13.4ZM12,19.2 L19.2,12Q19.2,12 19.2,12Q19.2,12 19.2,12L12,4.8Q12,4.8 12,4.8Q12,4.8 12,4.8L4.8,12Q4.8,12 4.8,12Q4.8,12 4.8,12L12,19.2Q12,19.2 12,19.2Q12,19.2 12,19.2Z"/>
</vector>

View File

@@ -0,0 +1,24 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/system_accent1_600">
<path android:fillColor="@android:color/white" android:pathData="M19.95,21Q16.725,21 13.663,19.562Q10.6,18.125 8.238,15.762Q5.875,13.4 4.438,10.337Q3,7.275 3,4.05Q3,3.6 3.3,3.3Q3.6,3 4.05,3H8.1Q8.45,3 8.725,3.225Q9,3.45 9.05,3.8L9.7,7.3Q9.75,7.65 9.688,7.937Q9.625,8.225 9.4,8.45L7,10.9Q8.05,12.7 9.625,14.275Q11.2,15.85 13.1,17L15.45,14.65Q15.675,14.425 16.038,14.312Q16.4,14.2 16.75,14.25L20.2,14.95Q20.55,15.025 20.775,15.287Q21,15.55 21,15.9V19.95Q21,20.4 20.7,20.7Q20.4,21 19.95,21Z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/system_accent1_600">
<path android:fillColor="@android:color/white"
android:pathData="M8,11Q8.425,11 8.713,10.712Q9,10.425 9,10Q9,9.575 8.713,9.287Q8.425,9 8,9Q7.575,9 7.287,9.287Q7,9.575 7,10Q7,10.425 7.287,10.712Q7.575,11 8,11ZM12,11Q12.425,11 12.713,10.712Q13,10.425 13,10Q13,9.575 12.713,9.287Q12.425,9 12,9Q11.575,9 11.288,9.287Q11,9.575 11,10Q11,10.425 11.288,10.712Q11.575,11 12,11ZM16,11Q16.425,11 16.712,10.712Q17,10.425 17,10Q17,9.575 16.712,9.287Q16.425,9 16,9Q15.575,9 15.288,9.287Q15,9.575 15,10Q15,10.425 15.288,10.712Q15.575,11 16,11ZM2,22V4Q2,3.175 2.588,2.587Q3.175,2 4,2H20Q20.825,2 21.413,2.587Q22,3.175 22,4V16Q22,16.825 21.413,17.413Q20.825,18 20,18H6ZM4,16H20Q20,16 20,16Q20,16 20,16V4Q20,4 20,4Q20,4 20,4H4Q4,4 4,4Q4,4 4,4V16ZM4,16V4Q4,4 4,4Q4,4 4,4Q4,4 4,4Q4,4 4,4V16Q4,16 4,16Q4,16 4,16Z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<?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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path android:fillColor="@android:color/white" android:pathData="M9,22 L7.65,17.45Q6.45,16.5 5.725,15.075Q5,13.65 5,12Q5,10.35 5.725,8.925Q6.45,7.5 7.65,6.55L9,2H15L16.35,6.55Q17.55,7.5 18.275,8.925Q19,10.35 19,12Q19,13.65 18.275,15.075Q17.55,16.5 16.35,17.45L15,22ZM12,17Q14.075,17 15.538,15.537Q17,14.075 17,12Q17,9.925 15.538,8.462Q14.075,7 12,7Q9.925,7 8.463,8.462Q7,9.925 7,12Q7,14.075 8.463,15.537Q9.925,17 12,17Z"/>
</vector>

View File

@@ -57,36 +57,39 @@
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:id="@+id/multiple_device_list"
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/constraint_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:orientation="vertical"
android:visibility="gone">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/device_list"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scrollbars="vertical"
android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/permission_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:fadeScrollbars="false"
app:layout_constraintHeight_max="220dp"
android:visibility="gone" />
<View
android:id="@+id/border_top"
style="@style/DeviceListBorder" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/device_list"
android:layout_width="match_parent"
android:scrollbars="vertical"
android:layout_marginBottom="12dp"
android:layout_height="200dp" />
<View
android:id="@+id/border_bottom"
app:layout_constraintBottom_toBottomOf="parent"
style="@style/DeviceListBorder" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/permission_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ProgressBar
android:id="@+id/spinner_multiple_device"
@@ -132,6 +135,8 @@
style="@style/NegativeButtonMultipleDevices"
android:textColor="?android:textColorPrimary"
android:visibility="gone"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:text="@string/consent_no" />
</LinearLayout>

View File

@@ -46,6 +46,7 @@
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="?android:attr/textColorPrimary"
style="@style/TextAppearance"
android:textSize="22sp" />
<TextView
@@ -58,6 +59,7 @@
android:layout_marginBottom="32dp"
android:gravity="center"
android:textColor="?android:attr/textColorSecondary"
style="@style/TextAppearance"
android:textSize="14sp" />
<LinearLayout
@@ -70,6 +72,7 @@
<Button
android:id="@+id/btn_back"
style="@style/VendorHelperBackButton"
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium"
android:text="@string/consent_back" />
</LinearLayout>

View File

@@ -39,6 +39,6 @@
android:layout_height="wrap_content"
android:paddingStart="24dp"
android:paddingEnd="24dp"
android:textAppearance="?android:attr/textAppearanceListItemSmall"/>
style="@style/TextAppearance"/>
</LinearLayout>

View File

@@ -34,26 +34,43 @@
android:contentDescription="@null"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_vertical"
android:padding="6dp">
android:padding="6dp"
android:layout_weight="1">
<TextView
android:id="@+id/permission_name"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textAppearance="?android:attr/textAppearanceListItemSmall"/>
android:layout_marginTop="2dp"
style="@style/TextAppearance"
android:textColor="?android:attr/textColorPrimary"/>
<TextView
android:id="@+id/permission_summary"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginTop="2dp"
style="@style/TextAppearance"
android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
<ImageButton
android:id="@+id/permission_expand_button"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/btn_expand_more"
android:layout_marginTop="8dp"
android:layout_marginStart="24dp"
android:background="@android:color/transparent"
android:clickable="false"
android:importantForAccessibility="no"
android:contentDescription="@null"/>
</LinearLayout>

View File

@@ -31,16 +31,13 @@
<string name="chooser_title">Choose a <xliff:g id="profile_name" example="watch">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%2$s</xliff:g>&lt;/strong&gt;</string>
<!-- Description of the privileges the application will get if associated with the companion device of WATCH profile (type) [CHAR LIMIT=NONE] -->
<string name="summary_watch">This app is needed to manage your <xliff:g id="device_name" example="My Watch">%1$s</xliff:g>. <xliff:g id="app_name" example="Android Wear">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions.</string>
<string name="summary_watch">The app is needed to manage your <xliff:g id="device_name" example="My Watch">%1$s</xliff:g>. <xliff:g id="app_name" example="Android Wear">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions.</string>
<!-- Description of the privileges the application will get if associated with the companion device of WATCH profile for singleDevice(type) [CHAR LIMIT=NONE] -->
<string name="summary_watch_single_device">The app is needed to manage your <xliff:g id="device_name" example="My Watch">%1$s</xliff:g>. <xliff:g id="app_name" example="Android Wear">%2$s</xliff:g> will be allowed to interact with these permissions:</string>
<!-- ================= DEVICE_PROFILE_APP_STREAMING ================= -->
<!-- Apps permission will be granted of APP_STREAMING profile [CHAR LIMIT=30] -->
<string name="permission_apps">Apps</string>
<!-- Description of apps permission of APP_STREAMING profile [CHAR LIMIT=NONE] -->
<string name="permission_apps_summary">Stream your phone\u2019s apps</string>
<!-- Confirmation for associating an application with a companion device of APP_STREAMING profile (type) [CHAR LIMIT=NONE] -->
<string name="title_app_streaming">Allow &lt;strong&gt;<xliff:g id="app_name" example="Exo">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone</string>
@@ -66,18 +63,6 @@
<!-- Description of the privileges the application will get if associated with the companion device of COMPUTER profile (type) [CHAR LIMIT=NONE] -->
<string name="summary_computer"></string>
<!-- Notification permission will be granted of COMPUTER profile [CHAR LIMIT=30] -->
<string name="permission_notification">Notifications</string>
<!-- Description of notification permission of COMPUTER profile [CHAR LIMIT=NONE] -->
<string name="permission_notification_summary">Can read all notifications, including information like contacts, messages, and photos</string>
<!-- Storage permission will be granted of COMPUTER profile [CHAR LIMIT=30] -->
<string name="permission_storage">Photos and media</string>
<!-- Description of storage permission of COMPUTER profile [CHAR LIMIT=NONE] -->
<string name="permission_storage_summary"></string>
<!-- Title of the helper dialog for COMPUTER profile [CHAR LIMIT=30]. -->
<string name="helper_title_computer">Google Play services</string>
@@ -117,4 +102,57 @@
<!--Description for information icon [CHAR LIMIT=30]-->
<string name="vendor_header_button_description">More Information Button</string>
<!-- ================= Permissions ================= -->
<!-- Phone permission will be granted of corresponding profile [CHAR LIMIT=30] -->
<string name="permission_phone">Phone</string>
<!-- SMS permission will be granted of corresponding profile [CHAR LIMIT=30] -->
<string name="permission_sms">SMS</string>
<!-- Contacts permission will be granted of corresponding profile [CHAR LIMIT=30] -->
<string name="permission_contacts">Contacts</string>
<!-- Calendar permission will be granted of corresponding profile [CHAR LIMIT=30] -->
<string name="permission_calendar">Calendar</string>
<!-- Calendar permission will be granted of corresponding profile [CHAR LIMIT=30] -->
<string name="permission_nearby_devices">Nearby devices</string>
<!-- Storage permission will be granted of corresponding profile [CHAR LIMIT=30] -->
<string name="permission_storage">Photos and media</string>
<!-- Notification permission will be granted of corresponding profile [CHAR LIMIT=30] -->
<string name="permission_notification">Notifications</string>
<!-- Apps permission will be granted of corresponding profile [CHAR LIMIT=30] -->
<string name="permission_app_streaming">Apps</string>
<!-- Description of phone permission of corresponding profile [CHAR LIMIT=NONE] -->
<string name="permission_phone_summary">Can access your phone number and network info. Required for making calls and VoIP, voicemail, call redirect, and editing call logs</string>
<!-- Description of SMS permission of corresponding profile [CHAR LIMIT=NONE] -->
<!-- TODO(b/253644212) Need the description for sms permission -->
<string name="permission_sms_summary"></string>
<!-- Description of contacts permission of corresponding profile [CHAR LIMIT=NONE] -->
<string name="permission_contacts_summary">Can read, create, or edit our contact list, as well as access the list of all accounts used on your device</string>
<!-- Description of calendar permission of corresponding profile [CHAR LIMIT=NONE] -->
<!-- TODO(b/253644212) Need the description for calendar permission -->
<string name="permission_calendar_summary"></string>
<!-- Description of nearby devices' permission of corresponding profile [CHAR LIMIT=NONE] -->
<!-- TODO(b/253644212) Need the description for nearby devices' permission -->
<string name="permission_nearby_devices_summary"></string>
<!-- Description of notification permission of corresponding profile [CHAR LIMIT=NONE] -->
<string name="permission_notification_summary">Can read all notifications, including information like contacts, messages, and photos</string>
<!-- Description of app streaming permission of corresponding profile [CHAR LIMIT=NONE] -->
<string name="permission_app_streaming_summary">Stream your phone\u2019s apps</string>
<!-- Description of storage permission of corresponding profile [CHAR LIMIT=NONE] -->
<string name="permission_storage_summary"></string>
</resources>

View File

@@ -36,7 +36,7 @@
</style>
<style name="DescriptionTitle"
parent="@*android:style/TextAppearance.Widget.Toolbar.Title">
parent="@android:style/TextAppearance.DeviceDefault.Medium">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">center</item>
@@ -46,7 +46,8 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="DescriptionSummary">
<style name="DescriptionSummary"
parent="@android:style/TextAppearance.DeviceDefault.Medium">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginTop">18dp</item>
@@ -61,6 +62,7 @@
<item name="android:layout_width">70dp</item>
<item name="android:layout_height">48dp</item>
<item name="android:textAllCaps">false</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">@android:color/system_neutral1_900</item>
<item name="android:background">@drawable/helper_back_button</item>
</style>
@@ -73,6 +75,7 @@
<item name="android:textAllCaps">false</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">@android:color/system_neutral1_900</item>
<item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item>
<item name="android:background">@drawable/btn_positive_bottom</item>
</style>
@@ -85,6 +88,7 @@
<item name="android:textSize">14sp</item>
<item name="android:textColor">@android:color/system_neutral1_900</item>
<item name="android:layout_marginTop">4dp</item>
<item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item>
<item name="android:background">@drawable/btn_negative_top</item>
</style>
@@ -93,13 +97,17 @@
<item name="android:layout_width">100dp</item>
<item name="android:layout_height">36dp</item>
<item name="android:textAllCaps">false</item>
<item name="android:textSize">14sp</item>
<item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item>
<item name="android:background">@drawable/btn_negative_multiple_devices</item>
</style>
<style name="DeviceListBorder">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">1dp</item>
<item name="android:background">@android:color/system_accent1_300</item>
<item name="android:layout_marginStart">32dp</item>
<item name="android:layout_marginEnd">32dp</item>
<item name="android:background">@android:color/system_neutral1_200</item>
</style>
<style name="Spinner"
@@ -115,4 +123,9 @@
<item name="android:fillViewport">true</item>
<item name="android:clipChildren">false</item>
</style>
<style name="TextAppearance">
<item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item>
</style>
</resources>

View File

@@ -31,9 +31,14 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE
import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState;
import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState.FINISHED_TIMEOUT;
import static com.android.companiondevicemanager.PermissionListAdapter.TYPE_APPS;
import static com.android.companiondevicemanager.PermissionListAdapter.TYPE_NOTIFICATION;
import static com.android.companiondevicemanager.PermissionListAdapter.TYPE_STORAGE;
import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_APP_STREAMING;
import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_CALENDAR;
import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_CONTACTS;
import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_NEARBY_DEVICES;
import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_NOTIFICATION;
import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_PHONE;
import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_SMS;
import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_STORAGE;
import static com.android.companiondevicemanager.Utils.getApplicationLabel;
import static com.android.companiondevicemanager.Utils.getHtmlFromResources;
import static com.android.companiondevicemanager.Utils.getIcon;
@@ -55,6 +60,9 @@ import android.companion.IAssociationRequestCallback;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.BlendMode;
import android.graphics.BlendModeColorFilter;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.MacAddress;
import android.os.Bundle;
@@ -64,6 +72,7 @@ import android.os.ResultReceiver;
import android.text.Spanned;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
@@ -72,12 +81,14 @@ import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@@ -140,8 +151,14 @@ public class CompanionDeviceActivity extends FragmentActivity implements
// Present for multiple devices' association requests only.
private Button mButtonNotAllowMultipleDevices;
// Present for top and bottom borders for permissions list and device list.
private View mBorderTop;
private View mBorderBottom;
private LinearLayout mAssociationConfirmationDialog;
private LinearLayout mMultipleDeviceList;
// Contains device list, permission list and top/bottom borders.
private ConstraintLayout mConstraintList;
// Only present for self-managed association requests.
private RelativeLayout mVendorHeader;
// The recycler view is only shown for multiple-device regular association request, after
@@ -150,7 +167,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements
private @Nullable DeviceListAdapter mDeviceAdapter;
// The recycler view is only shown for selfManaged association request.
// The recycler view is only shown for selfManaged and singleDevice association request.
private @Nullable RecyclerView mPermissionListRecyclerView;
private @Nullable PermissionListAdapter mPermissionListAdapter;
@@ -164,6 +181,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements
private @Nullable List<Integer> mPermissionTypes;
private LinearLayoutManager mPermissionsLayoutManager = new LinearLayoutManager(this);
@Override
public void onCreate(Bundle savedInstanceState) {
if (DEBUG) Log.d(TAG, "onCreate()");
@@ -212,7 +231,6 @@ public class CompanionDeviceActivity extends FragmentActivity implements
boolean forCancelDialog = intent.getBooleanExtra(EXTRA_FORCE_CANCEL_CONFIRMATION, false);
if (forCancelDialog) {
Log.i(TAG, "Cancelling the user confirmation");
cancel(/* discoveryTimeOut */ false,
@@ -285,10 +303,13 @@ public class CompanionDeviceActivity extends FragmentActivity implements
setContentView(R.layout.activity_confirmation);
mMultipleDeviceList = findViewById(R.id.multiple_device_list);
mConstraintList = findViewById(R.id.constraint_list);
mAssociationConfirmationDialog = findViewById(R.id.association_confirmation);
mVendorHeader = findViewById(R.id.vendor_header);
mBorderTop = findViewById(R.id.border_top);
mBorderBottom = findViewById(R.id.border_bottom);
mTitle = findViewById(R.id.title);
mSummary = findViewById(R.id.summary);
@@ -463,10 +484,11 @@ public class CompanionDeviceActivity extends FragmentActivity implements
return;
}
// TODO(b/253644212): Add maps for profile -> title, summary, permissions
switch (deviceProfile) {
case DEVICE_PROFILE_APP_STREAMING:
title = getHtmlFromResources(this, R.string.title_app_streaming, deviceName);
mPermissionTypes.add(TYPE_APPS);
mPermissionTypes.add(PERMISSION_APP_STREAMING);
break;
case DEVICE_PROFILE_AUTOMOTIVE_PROJECTION:
@@ -476,25 +498,27 @@ public class CompanionDeviceActivity extends FragmentActivity implements
case DEVICE_PROFILE_COMPUTER:
title = getHtmlFromResources(this, R.string.title_computer, deviceName);
mPermissionTypes.add(TYPE_NOTIFICATION);
mPermissionTypes.add(TYPE_STORAGE);
mPermissionTypes.addAll(Arrays.asList(PERMISSION_NOTIFICATION, PERMISSION_STORAGE));
break;
default:
throw new RuntimeException("Unsupported profile " + deviceProfile);
}
// Summary is not needed for selfManaged dialog.
mSummary.setVisibility(View.GONE);
mPermissionListAdapter.setPermissionType(mPermissionTypes);
mPermissionListRecyclerView.setAdapter(mPermissionListAdapter);
mPermissionListRecyclerView.setLayoutManager(new LinearLayoutManager(this));
setupPermissionList();
mTitle.setText(title);
mVendorHeaderName.setText(vendorName);
mDeviceListRecyclerView.setVisibility(View.GONE);
mProfileIcon.setVisibility(View.GONE);
mVendorHeader.setVisibility(View.VISIBLE);
mVendorHeader.setVisibility(View.VISIBLE);
mProfileIcon.setVisibility(View.GONE);
mDeviceListRecyclerView.setVisibility(View.GONE);
// Top and bottom borders should be gone for selfManaged dialog.
mBorderTop.setVisibility(View.GONE);
mBorderBottom.setVisibility(View.GONE);
}
private void initUiForSingleDevice(CharSequence appLabel) {
@@ -502,11 +526,15 @@ public class CompanionDeviceActivity extends FragmentActivity implements
final String deviceProfile = mRequest.getDeviceProfile();
mPermissionTypes = new ArrayList<>();
CompanionDeviceDiscoveryService.getScanResult().observe(this,
deviceFilterPairs -> updateSingleDeviceUi(
deviceFilterPairs, deviceProfile, appLabel));
mSingleDeviceSpinner.setVisibility(View.VISIBLE);
// Hide permission list and confirmation dialog first before the
// first matched device is found.
mPermissionListRecyclerView.setVisibility(View.GONE);
mDeviceListRecyclerView.setVisibility(View.GONE);
mAssociationConfirmationDialog.setVisibility(View.GONE);
@@ -537,11 +565,20 @@ public class CompanionDeviceActivity extends FragmentActivity implements
title = getHtmlFromResources(this, R.string.confirmation_title, appLabel, deviceName);
summary = getHtmlFromResources(this, R.string.summary_generic);
profileIcon = getIcon(this, R.drawable.ic_device_other);
// Summary is not needed for null profile.
mSummary.setVisibility(View.GONE);
mConstraintList.setVisibility(View.GONE);
} else if (deviceProfile.equals(DEVICE_PROFILE_WATCH)) {
title = getHtmlFromResources(this, R.string.confirmation_title, appLabel, profileName);
summary = getHtmlFromResources(this, R.string.summary_watch, deviceName, appLabel);
title = getHtmlFromResources(this, R.string.confirmation_title, appLabel, deviceName);
summary = getHtmlFromResources(
this, R.string.summary_watch_single_device, profileName, appLabel);
profileIcon = getIcon(this, R.drawable.ic_watch);
mPermissionTypes.addAll(Arrays.asList(
PERMISSION_NOTIFICATION, PERMISSION_PHONE, PERMISSION_SMS, PERMISSION_CONTACTS,
PERMISSION_CALENDAR, PERMISSION_NEARBY_DEVICES));
setupPermissionList();
} else {
throw new RuntimeException("Unsupported profile " + deviceProfile);
}
@@ -596,8 +633,9 @@ public class CompanionDeviceActivity extends FragmentActivity implements
// "Remove" consent button: users would need to click on the list item.
mButtonAllow.setVisibility(View.GONE);
mButtonNotAllow.setVisibility(View.GONE);
mDeviceListRecyclerView.setVisibility(View.VISIBLE);
mButtonNotAllowMultipleDevices.setVisibility(View.VISIBLE);
mMultipleDeviceList.setVisibility(View.VISIBLE);
mConstraintList.setVisibility(View.VISIBLE);
mMultipleDeviceSpinner.setVisibility(View.VISIBLE);
}
@@ -654,6 +692,80 @@ public class CompanionDeviceActivity extends FragmentActivity implements
return mApproved || mCancelled;
}
// Set up the mPermissionListRecyclerView, including set up the adapter,
// initiate the layoutManager for the recyclerview, add listeners for monitoring the scrolling
// and when mPermissionListRecyclerView is fully populated.
// Lastly, disable the Allow and Don't allow buttons.
private void setupPermissionList() {
mPermissionListAdapter.setPermissionType(mPermissionTypes);
mPermissionListRecyclerView.setAdapter(mPermissionListAdapter);
mPermissionListRecyclerView.setLayoutManager(mPermissionsLayoutManager);
disableButtons();
// Enable buttons once users scroll down to the bottom of the permission list.
mPermissionListRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (!recyclerView.canScrollVertically(1)) {
enableButtons();
}
}
});
// Enable buttons if last item in the permission list is visible to the users when
// mPermissionListRecyclerView is fully populated.
mPermissionListRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
LinearLayoutManager layoutManager =
(LinearLayoutManager) mPermissionListRecyclerView
.getLayoutManager();
int lastVisibleItemPosition =
layoutManager.findLastCompletelyVisibleItemPosition();
int numItems = mPermissionListRecyclerView.getAdapter().getItemCount();
if (lastVisibleItemPosition >= numItems - 1) {
enableButtons();
}
mPermissionListRecyclerView.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
}
});
mConstraintList.setVisibility(View.VISIBLE);
mPermissionListRecyclerView.setVisibility(View.VISIBLE);
}
// Disable and grey out the Allow and Don't allow buttons if the last permission in the
// permission list is not visible to the users.
private void disableButtons() {
mButtonAllow.setEnabled(false);
mButtonNotAllow.setEnabled(false);
mButtonAllow.setTextColor(
getResources().getColor(android.R.color.system_neutral1_400, null));
mButtonNotAllow.setTextColor(
getResources().getColor(android.R.color.system_neutral1_400, null));
mButtonAllow.getBackground().setColorFilter(
(new BlendModeColorFilter(Color.LTGRAY, BlendMode.DARKEN)));
mButtonNotAllow.getBackground().setColorFilter(
(new BlendModeColorFilter(Color.LTGRAY, BlendMode.DARKEN)));
}
// Enable and restore the color for the Allow and Don't allow buttons if the last permission in
// the permission list is visible to the users.
private void enableButtons() {
mButtonAllow.setEnabled(true);
mButtonNotAllow.setEnabled(true);
mButtonAllow.getBackground().setColorFilter(null);
mButtonNotAllow.getBackground().setColorFilter(null);
mButtonAllow.setTextColor(
getResources().getColor(android.R.color.system_neutral1_900, null));
mButtonNotAllow.setTextColor(
getResources().getColor(android.R.color.system_neutral1_900, null));
}
private final ResultReceiver mOnAssociationCreatedReceiver =
new ResultReceiver(Handler.getMain()) {
@Override

View File

@@ -27,6 +27,7 @@ import android.util.ArrayMap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
@@ -37,37 +38,58 @@ import java.util.Map;
class PermissionListAdapter extends RecyclerView.Adapter<PermissionListAdapter.ViewHolder> {
private final Context mContext;
private List<Integer> mPermissions;
// Add the expand buttons if permissions are more than PERMISSION_SIZE in the permission list.
private static final int PERMISSION_SIZE = 2;
static final int TYPE_NOTIFICATION = 0;
static final int TYPE_STORAGE = 1;
static final int TYPE_APPS = 2;
static final int PERMISSION_NOTIFICATION = 0;
static final int PERMISSION_STORAGE = 1;
static final int PERMISSION_APP_STREAMING = 2;
static final int PERMISSION_PHONE = 3;
static final int PERMISSION_SMS = 4;
static final int PERMISSION_CONTACTS = 5;
static final int PERMISSION_CALENDAR = 6;
static final int PERMISSION_NEARBY_DEVICES = 7;
private static final Map<Integer, Integer> sTitleMap;
static {
final Map<Integer, Integer> map = new ArrayMap<>();
map.put(TYPE_NOTIFICATION, R.string.permission_notification);
map.put(TYPE_STORAGE, R.string.permission_storage);
map.put(TYPE_APPS, R.string.permission_apps);
map.put(PERMISSION_NOTIFICATION, R.string.permission_notification);
map.put(PERMISSION_STORAGE, R.string.permission_storage);
map.put(PERMISSION_APP_STREAMING, R.string.permission_app_streaming);
map.put(PERMISSION_PHONE, R.string.permission_phone);
map.put(PERMISSION_SMS, R.string.permission_sms);
map.put(PERMISSION_CONTACTS, R.string.permission_contacts);
map.put(PERMISSION_CALENDAR, R.string.permission_calendar);
map.put(PERMISSION_NEARBY_DEVICES, R.string.permission_nearby_devices);
sTitleMap = unmodifiableMap(map);
}
private static final Map<Integer, Integer> sSummaryMap;
static {
final Map<Integer, Integer> map = new ArrayMap<>();
map.put(TYPE_NOTIFICATION, R.string.permission_notification_summary);
map.put(TYPE_STORAGE, R.string.permission_storage_summary);
map.put(TYPE_APPS, R.string.permission_apps_summary);
map.put(PERMISSION_NOTIFICATION, R.string.permission_notification_summary);
map.put(PERMISSION_STORAGE, R.string.permission_storage_summary);
map.put(PERMISSION_APP_STREAMING, R.string.permission_app_streaming_summary);
map.put(PERMISSION_PHONE, R.string.permission_phone_summary);
map.put(PERMISSION_SMS, R.string.permission_sms_summary);
map.put(PERMISSION_CONTACTS, R.string.permission_contacts_summary);
map.put(PERMISSION_CALENDAR, R.string.permission_calendar_summary);
map.put(PERMISSION_NEARBY_DEVICES, R.string.permission_nearby_devices_summary);
sSummaryMap = unmodifiableMap(map);
}
private static final Map<Integer, Integer> sIconMap;
static {
final Map<Integer, Integer> map = new ArrayMap<>();
map.put(TYPE_NOTIFICATION, R.drawable.ic_notifications);
map.put(TYPE_STORAGE, R.drawable.ic_storage);
map.put(TYPE_APPS, R.drawable.ic_apps);
map.put(PERMISSION_NOTIFICATION, R.drawable.ic_permission_notifications);
map.put(PERMISSION_STORAGE, R.drawable.ic_permission_storage);
map.put(PERMISSION_APP_STREAMING, R.drawable.ic_permission_app_streaming);
map.put(PERMISSION_PHONE, R.drawable.ic_permission_phone);
map.put(PERMISSION_SMS, R.drawable.ic_permission_sms);
map.put(PERMISSION_CONTACTS, R.drawable.ic_permission_contacts);
map.put(PERMISSION_CALENDAR, R.drawable.ic_permission_calendar);
map.put(PERMISSION_NEARBY_DEVICES, R.drawable.ic_permission_nearby_devices);
sIconMap = unmodifiableMap(map);
}
@@ -82,6 +104,29 @@ class PermissionListAdapter extends RecyclerView.Adapter<PermissionListAdapter.V
ViewHolder viewHolder = new ViewHolder(view);
viewHolder.mPermissionIcon.setImageDrawable(getIcon(mContext, sIconMap.get(viewType)));
if (viewHolder.mExpandButton.getTag() == null) {
viewHolder.mExpandButton.setTag(R.drawable.btn_expand_more);
}
// Add expand buttons if the permissions are more than PERMISSION_SIZE in this list.
if (mPermissions.size() > PERMISSION_SIZE) {
view.setOnClickListener(v -> {
if ((Integer) viewHolder.mExpandButton.getTag() == R.drawable.btn_expand_more) {
viewHolder.mExpandButton.setImageResource(R.drawable.btn_expand_less);
if (viewHolder.mSummary != null) {
viewHolder.mPermissionSummary.setText(viewHolder.mSummary);
}
viewHolder.mPermissionSummary.setVisibility(View.VISIBLE);
viewHolder.mExpandButton.setTag(R.drawable.btn_expand_less);
} else {
viewHolder.mExpandButton.setImageResource(R.drawable.btn_expand_more);
viewHolder.mPermissionSummary.setVisibility(View.GONE);
viewHolder.mExpandButton.setTag(R.drawable.btn_expand_more);
}
});
}
return viewHolder;
}
@@ -91,8 +136,15 @@ class PermissionListAdapter extends RecyclerView.Adapter<PermissionListAdapter.V
final Spanned title = getHtmlFromResources(mContext, sTitleMap.get(type));
final Spanned summary = getHtmlFromResources(mContext, sSummaryMap.get(type));
holder.mSummary = summary;
holder.mPermissionName.setText(title);
holder.mPermissionSummary.setText(summary);
if (mPermissions.size() <= PERMISSION_SIZE) {
holder.mPermissionSummary.setText(summary);
holder.mExpandButton.setVisibility(View.GONE);
} else {
holder.mPermissionSummary.setVisibility(View.GONE);
}
}
@Override
@@ -114,11 +166,14 @@ class PermissionListAdapter extends RecyclerView.Adapter<PermissionListAdapter.V
private final TextView mPermissionName;
private final TextView mPermissionSummary;
private final ImageView mPermissionIcon;
private final ImageButton mExpandButton;
private Spanned mSummary = null;
ViewHolder(View itemView) {
super(itemView);
mPermissionName = itemView.findViewById(R.id.permission_name);
mPermissionSummary = itemView.findViewById(R.id.permission_summary);
mPermissionIcon = itemView.findViewById(R.id.permission_icon);
mExpandButton = itemView.findViewById(R.id.permission_expand_button);
}
}