Add layout for 1x1 size, update 2x1
This allows users a smaller width resize for the People Tile widget, and adjust the view accordingly after resize. Implements 1x1 and 2x1 mocks, with polish remaining for 2x1. Also fixes a crash when launching the conversation picker and bug on removing missed call notifications. Bug: 182377480 Test: PeopleSpaceUtilsTest Change-Id: Ie3b16fb3e348f8edd7bb314c9f43408dca7b43e2
This commit is contained in:
24
packages/SystemUI/res/drawable/ic_message.xml
Normal file
24
packages/SystemUI/res/drawable/ic_message.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
~ Copyright (C) 2021 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" xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48"
|
||||
android:width="48dp"
|
||||
android:height="48dp">
|
||||
<path
|
||||
android:pathData="M40 4H8C5.79 4 4.02 5.79 4.02 8L4 44l8 -8h28c2.21 0 4 -1.79 4 -4V8c0 -2.21 -1.79 -4 -4 -4zM12 18h24v4H12v-4zm16 10H12v-4h16v4zm8 -12H12v-4h24v4z"
|
||||
android:fillColor="#FF000000" />
|
||||
</vector>
|
||||
28
packages/SystemUI/res/drawable/ic_photo_camera.xml
Normal file
28
packages/SystemUI/res/drawable/ic_photo_camera.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<!--
|
||||
~ Copyright (C) 2021 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.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
|
||||
</vector>
|
||||
@@ -28,48 +28,27 @@
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center"
|
||||
android:paddingVertical="2dp"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<LinearLayout
|
||||
android:background="@drawable/people_space_new_story_outline"
|
||||
android:id="@+id/person_icon_with_story"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp">
|
||||
<ImageView
|
||||
android:id="@+id/person_icon_inside_ring"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"/>
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/person_icon_only"
|
||||
android:id="@+id/person_icon"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/package_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="-20dp"
|
||||
android:layout_marginTop="22dp"/>
|
||||
|
||||
android:id="@+id/availability"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:background="@drawable/circle_green_10dp"/>
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingStart="4dp"
|
||||
android:gravity="top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/availability"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:background="@drawable/circle_green_10dp"/>
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:text="@string/empty_user_name"
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2021 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.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<RelativeLayout
|
||||
android:background="@drawable/people_space_tile_view_card"
|
||||
android:id="@+id/item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<include layout="@layout/punctuation_layout"/>
|
||||
<RelativeLayout
|
||||
android:gravity="start"
|
||||
android:id="@+id/column_one"
|
||||
android:paddingVertical="10dp"
|
||||
android:paddingStart="8dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
<TextView
|
||||
android:id="@+id/subtext"
|
||||
android:layout_toStartOf="@+id/content_layout"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:gravity="top|start"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="12sp"
|
||||
android:maxWidth="60dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"/>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/avatar_and_app_icon"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout
|
||||
android:id="@+id/person_icon_with_story"
|
||||
android:background="@drawable/people_space_new_story_outline"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp">
|
||||
<ImageView
|
||||
android:id="@+id/person_icon_inside_ring"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"/>
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/person_icon_only"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"/>
|
||||
<ImageView
|
||||
android:id="@id/package_icon"
|
||||
android:layout_marginStart="-16dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="32dp"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/content_layout"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toEndOf="@id/column_one"
|
||||
android:gravity="top|end"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:id="@+id/content"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:gravity="top|end"
|
||||
android:textSize="12sp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"/>
|
||||
<LinearLayout
|
||||
android:id="@+id/content_background"
|
||||
android:background="@drawable/people_space_content_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:adjustViewBounds="true"
|
||||
android:maxHeight="44dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerCrop"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/person_label"
|
||||
android:paddingBottom="10dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:gravity="start|bottom"
|
||||
android:layout_toEndOf="@id/column_one"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@id/content_layout"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:id="@+id/availability"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:paddingVertical="2dp"
|
||||
android:background="@drawable/circle_green_10dp"/>
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
@@ -1,44 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2020 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
~ Copyright (C) 2020 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
android:background="@drawable/people_space_tile_view_card"
|
||||
android:id="@+id/item"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="center"
|
||||
android:padding="8dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<RelativeLayout
|
||||
android:gravity="start"
|
||||
android:id="@+id/column_one"
|
||||
android:paddingVertical="8dp"
|
||||
android:paddingStart="8dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:gravity="top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:gravity="start"
|
||||
android:id="@+id/person_icon"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"/>
|
||||
<ImageView
|
||||
android:id="@+id/availability"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:background="@drawable/circle_green_10dp"/>
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:gravity="top|start"
|
||||
android:paddingStart="12dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:id="@+id/subtext"
|
||||
android:text="@string/empty_user_name"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="12sp"
|
||||
android:paddingBottom="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"/>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/content_background"
|
||||
android:background="@drawable/people_space_content_background"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:gravity="center"
|
||||
@@ -46,105 +71,33 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerCrop"/>
|
||||
<ImageView
|
||||
android:id="@+id/status_defined_icon"
|
||||
android:gravity="start|top"
|
||||
android:layout_marginStart="-52dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/avatar_and_app_icon"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:paddingStart="4dp"
|
||||
android:gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout
|
||||
android:id="@+id/person_icon_with_story"
|
||||
android:background="@drawable/people_space_new_story_outline"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp">
|
||||
<ImageView
|
||||
android:id="@+id/person_icon_inside_ring"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"/>
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/person_icon_only"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"/>
|
||||
<ImageView
|
||||
android:id="@id/package_icon"
|
||||
android:layout_marginStart="-16dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="32dp"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/content_layout"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toEndOf="@id/column_one"
|
||||
android:gravity="top|end"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:id="@+id/text_content"
|
||||
android:text="@string/empty_status"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="12sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:singleLine="false"
|
||||
android:ellipsize="end"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/person_label"
|
||||
android:paddingBottom="10dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:gravity="start|bottom"
|
||||
android:layout_toEndOf="@id/column_one"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@id/content_layout"
|
||||
android:orientation="vertical"
|
||||
android:gravity="bottom"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="4dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="12sp"
|
||||
android:paddingVertical="2dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:visibility="gone"
|
||||
android:ellipsize="end"/>
|
||||
<ImageView
|
||||
android:id="@+id/availability"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:paddingVertical="2dp"
|
||||
android:background="@drawable/circle_green_10dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/empty_user_name"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp"
|
||||
@@ -152,6 +105,13 @@
|
||||
android:ellipsize="end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<ImageView
|
||||
android:id="@+id/predefined_icon"
|
||||
android:gravity="end"
|
||||
android:paddingStart="6dp"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="18dp"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
59
packages/SystemUI/res/layout/people_space_small_view.xml
Normal file
59
packages/SystemUI/res/layout/people_space_small_view.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (C) 2021 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.
|
||||
-->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/people_space_tile_view_card"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="4dp"
|
||||
android:paddingVertical="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/person_icon"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/predefined_icon"
|
||||
android:layout_gravity="center"
|
||||
android:paddingTop="4dp"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="22dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_gravity="center"
|
||||
android:paddingTop="4dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
@@ -15,10 +15,11 @@
|
||||
-->
|
||||
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:minWidth="140dp"
|
||||
android:minHeight="55dp"
|
||||
android:minResizeWidth="110dp"
|
||||
android:minResizeHeight="55dp"
|
||||
android:minWidth="120dp"
|
||||
android:minHeight="54dp"
|
||||
android:minResizeWidth="60dp"
|
||||
android:minResizeHeight="54dp"
|
||||
android:maxResizeHeight="207dp"
|
||||
android:updatePeriodMillis="60000"
|
||||
android:description="@string/people_tile_description"
|
||||
android:previewLayout="@layout/people_space_placeholder_layout"
|
||||
|
||||
@@ -110,16 +110,16 @@ public class PeopleProvider extends ContentProvider {
|
||||
}
|
||||
|
||||
if (DEBUG) Log.i(TAG, "Returning tile preview for shortcutId: " + shortcutId);
|
||||
RemoteViews view = PeopleSpaceUtils.createRemoteViews(getContext(), tile, 0);
|
||||
final Bundle bundle = new Bundle();
|
||||
RemoteViews view = PeopleSpaceUtils.createRemoteViews(getContext(), tile, 0, bundle);
|
||||
bundle.putParcelable(PeopleProviderUtils.RESPONSE_KEY_REMOTE_VIEWS, view);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
private boolean doesCallerHavePermission() {
|
||||
return getContext().checkPermission(
|
||||
PeopleProviderUtils.GET_PEOPLE_TILE_PREVIEW_PERMISSION,
|
||||
Binder.getCallingPid(), Binder.getCallingUid())
|
||||
PeopleProviderUtils.GET_PEOPLE_TILE_PREVIEW_PERMISSION,
|
||||
Binder.getCallingPid(), Binder.getCallingUid())
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@ import static android.app.people.ConversationStatus.ACTIVITY_MEDIA;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_NEW_STORY;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_UPCOMING_BIRTHDAY;
|
||||
import static android.app.people.ConversationStatus.AVAILABILITY_AVAILABLE;
|
||||
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT;
|
||||
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH;
|
||||
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT;
|
||||
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.INotificationManager;
|
||||
@@ -41,6 +45,7 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.graphics.Bitmap;
|
||||
@@ -52,13 +57,16 @@ import android.icu.text.MeasureFormat;
|
||||
import android.icu.util.Measure;
|
||||
import android.icu.util.MeasureUnit;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.ContactsContract;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.ConversationChannelWrapper;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.text.TextUtils;
|
||||
import android.util.IconDrawableFactory;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
@@ -110,11 +118,17 @@ public class PeopleSpaceUtils {
|
||||
public static final String SHORTCUT_ID = "shortcut_id";
|
||||
|
||||
public static final String EMPTY_STRING = "";
|
||||
public static final int INVALID_WIDGET_ID = -1;
|
||||
public static final int INVALID_USER_ID = -1;
|
||||
|
||||
public static final PeopleTileKey EMPTY_KEY =
|
||||
new PeopleTileKey(EMPTY_STRING, INVALID_USER_ID, EMPTY_STRING);
|
||||
public static final int SMALL_LAYOUT = 0;
|
||||
public static final int MEDIUM_LAYOUT = 1;
|
||||
@VisibleForTesting
|
||||
static final int REQUIRED_WIDTH_FOR_MEDIUM = 146;
|
||||
private static final int AVATAR_SIZE_FOR_MEDIUM = 56;
|
||||
private static final int DEFAULT_WIDTH = 146;
|
||||
private static final int DEFAULT_HEIGHT = 92;
|
||||
|
||||
private static final Pattern DOUBLE_EXCLAMATION_PATTERN = Pattern.compile("[!][!]+");
|
||||
private static final Pattern DOUBLE_QUESTION_PATTERN = Pattern.compile("[?][?]+");
|
||||
@@ -208,7 +222,8 @@ public class PeopleSpaceUtils {
|
||||
//TODO: Delete app widget id when crash is fixed (b/172932636)
|
||||
continue;
|
||||
}
|
||||
updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId, tile);
|
||||
Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
|
||||
updateAppWidgetViews(appWidgetManager, context, appWidgetId, tile, options);
|
||||
widgetIdToTile.put(appWidgetId, tile);
|
||||
}
|
||||
getBirthdaysOnBackgroundThread(context, appWidgetManager, widgetIdToTile, appWidgetIds);
|
||||
@@ -343,7 +358,10 @@ public class PeopleSpaceUtils {
|
||||
.stream()
|
||||
.filter(entry -> entry.getRanking() != null
|
||||
&& entry.getRanking().getConversationShortcutInfo() != null)
|
||||
.collect(Collectors.toMap(PeopleTileKey::new, e -> e));
|
||||
.collect(Collectors.toMap(PeopleTileKey::new, e -> e,
|
||||
// Handle duplicate keys to avoid crashes.
|
||||
(e1, e2) -> e1.getSbn().getNotification().when
|
||||
> e2.getSbn().getNotification().when ? e1 : e2));
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Number of visible notifications:" + visibleNotifications.size());
|
||||
}
|
||||
@@ -401,9 +419,11 @@ public class PeopleSpaceUtils {
|
||||
|
||||
/** Creates a {@link RemoteViews} for {@code tile}. */
|
||||
public static RemoteViews createRemoteViews(Context context,
|
||||
PeopleSpaceTile tile, int appWidgetId) {
|
||||
RemoteViews viewsForTile = getViewForTile(context, tile);
|
||||
RemoteViews views = setCommonRemoteViewsFields(context, viewsForTile, tile);
|
||||
PeopleSpaceTile tile, int appWidgetId, Bundle options) {
|
||||
int layoutSize = getLayoutSize(context, options);
|
||||
RemoteViews viewsForTile = getViewForTile(context, tile, layoutSize);
|
||||
int maxAvatarSize = getMaxAvatarSize(context, options, layoutSize);
|
||||
RemoteViews views = setCommonRemoteViewsFields(context, viewsForTile, tile, maxAvatarSize);
|
||||
return setLaunchIntents(context, views, tile, appWidgetId);
|
||||
}
|
||||
|
||||
@@ -411,15 +431,16 @@ public class PeopleSpaceUtils {
|
||||
* The prioritization for the {@code tile} content is missed calls, followed by notification
|
||||
* content, then birthdays, then the most recent status, and finally last interaction.
|
||||
*/
|
||||
private static RemoteViews getViewForTile(Context context, PeopleSpaceTile tile) {
|
||||
private static RemoteViews getViewForTile(Context context, PeopleSpaceTile tile,
|
||||
int layoutSize) {
|
||||
if (Objects.equals(tile.getNotificationCategory(), CATEGORY_MISSED_CALL)) {
|
||||
if (DEBUG) Log.d(TAG, "Create missed call view");
|
||||
return createMissedCallRemoteViews(context, tile);
|
||||
return createMissedCallRemoteViews(context, tile, layoutSize);
|
||||
}
|
||||
|
||||
if (tile.getNotificationKey() != null) {
|
||||
if (DEBUG) Log.d(TAG, "Create notification view");
|
||||
return createNotificationRemoteViews(context, tile);
|
||||
return createNotificationRemoteViews(context, tile, layoutSize);
|
||||
}
|
||||
|
||||
// TODO: Add sorting when we expose timestamp of statuses.
|
||||
@@ -429,7 +450,7 @@ public class PeopleSpaceUtils {
|
||||
ConversationStatus birthdayStatus = getBirthdayStatus(tile, statusesForEntireView);
|
||||
if (birthdayStatus != null) {
|
||||
if (DEBUG) Log.d(TAG, "Create birthday view");
|
||||
return createStatusRemoteViews(context, birthdayStatus);
|
||||
return createStatusRemoteViews(context, birthdayStatus, layoutSize);
|
||||
}
|
||||
|
||||
if (!statusesForEntireView.isEmpty()) {
|
||||
@@ -437,10 +458,48 @@ public class PeopleSpaceUtils {
|
||||
Log.d(TAG,
|
||||
"Create status view for: " + statusesForEntireView.get(0).getActivity());
|
||||
}
|
||||
return createStatusRemoteViews(context, statusesForEntireView.get(0));
|
||||
return createStatusRemoteViews(context, statusesForEntireView.get(0), layoutSize);
|
||||
}
|
||||
|
||||
return createLastInteractionRemoteViews(context, tile);
|
||||
return createLastInteractionRemoteViews(context, tile, layoutSize);
|
||||
}
|
||||
|
||||
/** Calculates the best layout relative to the size in {@code options}. */
|
||||
private static int getLayoutSize(Context context, Bundle options) {
|
||||
int display = context.getResources().getConfiguration().orientation;
|
||||
int width = display == Configuration.ORIENTATION_PORTRAIT
|
||||
? options.getInt(OPTION_APPWIDGET_MIN_WIDTH, DEFAULT_WIDTH) : options.getInt(
|
||||
OPTION_APPWIDGET_MAX_WIDTH, DEFAULT_WIDTH);
|
||||
int height = display == Configuration.ORIENTATION_PORTRAIT ? options.getInt(
|
||||
OPTION_APPWIDGET_MAX_HEIGHT, DEFAULT_HEIGHT)
|
||||
: options.getInt(OPTION_APPWIDGET_MIN_HEIGHT, DEFAULT_HEIGHT);
|
||||
// Small layout used below a certain minimum width with any height.
|
||||
if (width < REQUIRED_WIDTH_FOR_MEDIUM) {
|
||||
if (DEBUG) Log.d(TAG, "Small view for width: " + width + " height: " + height);
|
||||
return SMALL_LAYOUT;
|
||||
}
|
||||
if (DEBUG) Log.d(TAG, "Medium view for width: " + width + " height: " + height);
|
||||
return MEDIUM_LAYOUT;
|
||||
}
|
||||
|
||||
/** Returns the max avatar size for {@code layoutSize} under the current {@code options}. */
|
||||
private static int getMaxAvatarSize(Context context, Bundle options, int layoutSize) {
|
||||
int avatarHeightSpace = AVATAR_SIZE_FOR_MEDIUM;
|
||||
int avatarWidthSpace = AVATAR_SIZE_FOR_MEDIUM;
|
||||
|
||||
if (layoutSize == SMALL_LAYOUT) {
|
||||
int display = context.getResources().getConfiguration().orientation;
|
||||
int width = display == Configuration.ORIENTATION_PORTRAIT
|
||||
? options.getInt(OPTION_APPWIDGET_MIN_WIDTH, DEFAULT_WIDTH) : options.getInt(
|
||||
OPTION_APPWIDGET_MAX_WIDTH, DEFAULT_WIDTH);
|
||||
int height = display == Configuration.ORIENTATION_PORTRAIT ? options.getInt(
|
||||
OPTION_APPWIDGET_MAX_HEIGHT, DEFAULT_HEIGHT)
|
||||
: options.getInt(OPTION_APPWIDGET_MIN_HEIGHT, DEFAULT_HEIGHT);
|
||||
avatarHeightSpace = height - (8 + 4 + 18 + 8);
|
||||
avatarWidthSpace = width - (4 + 4);
|
||||
}
|
||||
if (DEBUG) Log.d(TAG, "Height: " + avatarHeightSpace + " width: " + avatarWidthSpace);
|
||||
return Math.min(avatarHeightSpace, avatarWidthSpace);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -478,14 +537,22 @@ public class PeopleSpaceUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static RemoteViews createStatusRemoteViews(Context context, ConversationStatus status) {
|
||||
RemoteViews views = new RemoteViews(
|
||||
context.getPackageName(), R.layout.people_space_small_avatar_tile);
|
||||
private static RemoteViews createStatusRemoteViews(Context context, ConversationStatus status,
|
||||
int layoutSize) {
|
||||
int layout = layoutSize == SMALL_LAYOUT ? R.layout.people_space_small_view
|
||||
: R.layout.people_space_small_avatar_tile;
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), layout);
|
||||
CharSequence statusText = status.getDescription();
|
||||
if (TextUtils.isEmpty(statusText)) {
|
||||
statusText = getStatusTextByType(context, status.getActivity());
|
||||
}
|
||||
views.setTextViewText(R.id.status, statusText);
|
||||
views.setViewVisibility(R.id.subtext, View.GONE);
|
||||
views.setViewVisibility(R.id.text_content, View.VISIBLE);
|
||||
TypedValue typedValue = new TypedValue();
|
||||
context.getTheme().resolveAttribute(android.R.attr.textColorSecondary, typedValue, true);
|
||||
int secondaryTextColor = context.getColor(typedValue.resourceId);
|
||||
views.setInt(R.id.text_content, "setTextColor", secondaryTextColor);
|
||||
views.setTextViewText(R.id.text_content, statusText);
|
||||
Icon statusIcon = status.getIcon();
|
||||
if (statusIcon != null) {
|
||||
views.setImageViewIcon(R.id.image, statusIcon);
|
||||
@@ -494,6 +561,8 @@ public class PeopleSpaceUtils {
|
||||
views.setViewVisibility(R.id.content_background, View.GONE);
|
||||
}
|
||||
// TODO: Set status pre-defined icons
|
||||
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_person);
|
||||
ensurePredefinedIconVisibleOnSmallView(views, layoutSize);
|
||||
return views;
|
||||
}
|
||||
|
||||
@@ -519,7 +588,7 @@ public class PeopleSpaceUtils {
|
||||
}
|
||||
|
||||
private static RemoteViews setCommonRemoteViewsFields(Context context, RemoteViews views,
|
||||
PeopleSpaceTile tile) {
|
||||
PeopleSpaceTile tile, int maxAvatarSize) {
|
||||
try {
|
||||
boolean isAvailable =
|
||||
tile.getStatuses() != null && tile.getStatuses().stream().anyMatch(
|
||||
@@ -532,27 +601,20 @@ public class PeopleSpaceUtils {
|
||||
boolean hasNewStory =
|
||||
tile.getStatuses() != null && tile.getStatuses().stream().anyMatch(
|
||||
c -> c.getActivity() == ACTIVITY_NEW_STORY);
|
||||
if (hasNewStory) {
|
||||
views.setViewVisibility(R.id.person_icon_with_story, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.person_icon_only, View.GONE);
|
||||
views.setImageViewIcon(R.id.person_icon_inside_ring, tile.getUserIcon());
|
||||
} else {
|
||||
views.setViewVisibility(R.id.person_icon_with_story, View.GONE);
|
||||
views.setViewVisibility(R.id.person_icon_only, View.VISIBLE);
|
||||
views.setImageViewIcon(R.id.person_icon_only, tile.getUserIcon());
|
||||
}
|
||||
|
||||
views.setTextViewText(R.id.name, tile.getUserName().toString());
|
||||
views.setImageViewIcon(R.id.person_icon, tile.getUserIcon());
|
||||
views.setBoolean(R.id.content_background, "setClipToOutline", true);
|
||||
Icon icon = tile.getUserIcon();
|
||||
PeopleStoryIconFactory storyIcon = new PeopleStoryIconFactory(context,
|
||||
context.getPackageManager(),
|
||||
IconDrawableFactory.newInstance(context, false),
|
||||
maxAvatarSize);
|
||||
Drawable drawable = icon.loadDrawable(context);
|
||||
Drawable personDrawable = storyIcon.getPeopleTileDrawable(drawable,
|
||||
tile.getPackageName(), getUserId(tile), tile.isImportantConversation(),
|
||||
hasNewStory);
|
||||
Bitmap bitmap = convertDrawableToBitmap(personDrawable);
|
||||
views.setImageViewBitmap(R.id.person_icon, bitmap);
|
||||
|
||||
views.setImageViewBitmap(
|
||||
R.id.package_icon,
|
||||
PeopleSpaceUtils.convertDrawableToBitmap(
|
||||
context.getPackageManager().getApplicationIcon(
|
||||
tile.getPackageName())
|
||||
)
|
||||
);
|
||||
return views;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to set common fields: " + e);
|
||||
@@ -585,47 +647,77 @@ public class PeopleSpaceUtils {
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to add launch intents: " + e);
|
||||
}
|
||||
|
||||
return views;
|
||||
}
|
||||
|
||||
private static RemoteViews createMissedCallRemoteViews(Context context,
|
||||
PeopleSpaceTile tile) {
|
||||
RemoteViews views = new RemoteViews(
|
||||
context.getPackageName(), R.layout.people_space_small_avatar_tile);
|
||||
views.setTextViewText(R.id.status, tile.getNotificationContent());
|
||||
views.setImageViewResource(R.id.status_defined_icon, R.drawable.ic_phone_missed);
|
||||
PeopleSpaceTile tile, int layoutSize) {
|
||||
int layout = layoutSize == SMALL_LAYOUT ? R.layout.people_space_small_view
|
||||
: R.layout.people_space_small_avatar_tile;
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), layout);
|
||||
views.setViewVisibility(R.id.subtext, View.GONE);
|
||||
views.setViewVisibility(R.id.text_content, View.VISIBLE);
|
||||
views.setTextViewText(R.id.text_content, tile.getNotificationContent());
|
||||
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_phone_missed);
|
||||
ensurePredefinedIconVisibleOnSmallView(views, layoutSize);
|
||||
views.setBoolean(R.id.content_background, "setClipToOutline", true);
|
||||
return views;
|
||||
}
|
||||
|
||||
private static void ensurePredefinedIconVisibleOnSmallView(RemoteViews views, int layoutSize) {
|
||||
if (layoutSize == SMALL_LAYOUT) {
|
||||
views.setViewVisibility(R.id.name, View.GONE);
|
||||
views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private static RemoteViews createNotificationRemoteViews(Context context,
|
||||
PeopleSpaceTile tile) {
|
||||
RemoteViews views = new RemoteViews(
|
||||
context.getPackageName(), R.layout.people_space_notification_content_tile);
|
||||
PeopleSpaceTile tile, int layoutSize) {
|
||||
int layout = layoutSize == SMALL_LAYOUT ? R.layout.people_space_small_view
|
||||
: R.layout.people_space_small_avatar_tile;
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), layout);
|
||||
if (layoutSize != MEDIUM_LAYOUT) {
|
||||
views.setViewVisibility(R.id.name, View.GONE);
|
||||
views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
|
||||
}
|
||||
Uri image = tile.getNotificationDataUri();
|
||||
ensurePredefinedIconVisibleOnSmallView(views, layoutSize);
|
||||
if (image != null) {
|
||||
// TODO: Use NotificationInlineImageCache
|
||||
views.setImageViewUri(R.id.image, image);
|
||||
views.setViewVisibility(R.id.content_background, View.VISIBLE);
|
||||
views.setBoolean(R.id.content_background, "setClipToOutline", true);
|
||||
views.setViewVisibility(R.id.content, View.GONE);
|
||||
views.setViewVisibility(R.id.text_content, View.GONE);
|
||||
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_photo_camera);
|
||||
} else {
|
||||
CharSequence content = tile.getNotificationContent();
|
||||
views = setPunctuationRemoteViewsFields(views, content);
|
||||
views.setTextViewText(R.id.content, content);
|
||||
views.setViewVisibility(R.id.content, View.VISIBLE);
|
||||
views.setTextViewText(R.id.text_content, tile.getNotificationContent());
|
||||
// TODO: Measure max lines from height.
|
||||
views.setInt(R.id.text_content, "setMaxLines", 2);
|
||||
TypedValue typedValue = new TypedValue();
|
||||
context.getTheme().resolveAttribute(android.R.attr.textColorPrimary, typedValue, true);
|
||||
int primaryTextColor = context.getColor(typedValue.resourceId);
|
||||
views.setInt(R.id.text_content, "setTextColor", primaryTextColor);
|
||||
views.setViewVisibility(R.id.text_content, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.content_background, View.GONE);
|
||||
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_message);
|
||||
}
|
||||
// TODO: Set subtext as Group Sender name once storing the name in PeopleSpaceTile.
|
||||
views.setTextViewText(R.id.subtext, PeopleSpaceUtils.getLastInteractionString(
|
||||
context, tile.getLastInteractionTimestamp()));
|
||||
views.setViewVisibility(R.id.subtext, View.GONE);
|
||||
return views;
|
||||
}
|
||||
|
||||
private static RemoteViews createLastInteractionRemoteViews(Context context,
|
||||
PeopleSpaceTile tile) {
|
||||
RemoteViews views = new RemoteViews(
|
||||
context.getPackageName(), R.layout.people_space_large_avatar_tile);
|
||||
PeopleSpaceTile tile, int layoutSize) {
|
||||
int layout = layoutSize == SMALL_LAYOUT ? R.layout.people_space_small_view
|
||||
: R.layout.people_space_large_avatar_tile;
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), layout);
|
||||
if (layoutSize == SMALL_LAYOUT) {
|
||||
views.setViewVisibility(R.id.name, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.predefined_icon, View.GONE);
|
||||
}
|
||||
String status = PeopleSpaceUtils.getLastInteractionString(
|
||||
context, tile.getLastInteractionTimestamp());
|
||||
views.setTextViewText(R.id.last_interaction, status);
|
||||
@@ -900,18 +992,22 @@ public class PeopleSpaceUtils {
|
||||
removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId);
|
||||
}
|
||||
|
||||
/** Updates tile in app widget options and the current view. */
|
||||
public static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager,
|
||||
Context context, int appWidgetId, PeopleSpaceTile tile) {
|
||||
AppWidgetOptionsHelper.setPeopleTile(appWidgetManager, appWidgetId, tile);
|
||||
|
||||
private static void updateAppWidgetViews(AppWidgetManager appWidgetManager,
|
||||
Context context, int appWidgetId, PeopleSpaceTile tile, Bundle options) {
|
||||
if (DEBUG) Log.d(TAG, "Widget: " + appWidgetId + ", " + tile.getUserName());
|
||||
RemoteViews views = createRemoteViews(context, tile, appWidgetId);
|
||||
RemoteViews views = createRemoteViews(context, tile, appWidgetId, options);
|
||||
|
||||
// Tell the AppWidgetManager to perform an update on the current app widget.
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
}
|
||||
|
||||
/** Updates tile in app widget options and the current view. */
|
||||
public static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager,
|
||||
Context context, int appWidgetId, PeopleSpaceTile tile) {
|
||||
Bundle options = AppWidgetOptionsHelper.setPeopleTile(appWidgetManager, appWidgetId, tile);
|
||||
updateAppWidgetViews(appWidgetManager, context, appWidgetId, tile, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns lookup keys for all contacts with a birthday today.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.people;
|
||||
|
||||
import android.annotation.ColorInt;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.IconDrawableFactory;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import com.android.launcher3.icons.BaseIconFactory;
|
||||
import com.android.systemui.R;
|
||||
|
||||
class PeopleStoryIconFactory extends BaseIconFactory {
|
||||
|
||||
private static final int PADDING = 2;
|
||||
private static final int RING_WIDTH = 2;
|
||||
private static final int MAX_BADGE_SIZE = 36;
|
||||
|
||||
final PackageManager mPackageManager;
|
||||
final IconDrawableFactory mIconDrawableFactory;
|
||||
private int mImportantConversationColor;
|
||||
private int mAccentColor;
|
||||
private float mDensity;
|
||||
private float mIconSize;
|
||||
|
||||
PeopleStoryIconFactory(Context context, PackageManager pm,
|
||||
IconDrawableFactory iconDrawableFactory, int iconSizeDp) {
|
||||
super(context, context.getResources().getConfiguration().densityDpi,
|
||||
(int) (iconSizeDp * context.getResources().getDisplayMetrics().density));
|
||||
mDensity = context.getResources().getDisplayMetrics().density;
|
||||
mIconSize = mDensity * iconSizeDp;
|
||||
mPackageManager = pm;
|
||||
mIconDrawableFactory = iconDrawableFactory;
|
||||
mImportantConversationColor = context.getColor(R.color.important_conversation);
|
||||
TypedValue typedValue = new TypedValue();
|
||||
context.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true);
|
||||
mAccentColor = context.getColor(typedValue.resourceId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the {@link Drawable} that represents the app icon, badged with the work profile icon
|
||||
* if appropriate.
|
||||
*/
|
||||
private Drawable getAppBadge(String packageName, int userId) {
|
||||
Drawable badge = null;
|
||||
try {
|
||||
final ApplicationInfo appInfo = mPackageManager.getApplicationInfoAsUser(
|
||||
packageName, PackageManager.GET_META_DATA, userId);
|
||||
badge = mIconDrawableFactory.getBadgedIcon(appInfo, userId);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
badge = mPackageManager.getDefaultActivityIcon();
|
||||
}
|
||||
return badge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Drawable} for the entire conversation. The shortcut icon will be badged
|
||||
* with the launcher icon of the app specified by packageName.
|
||||
*/
|
||||
public Drawable getPeopleTileDrawable(Drawable headDrawable, String packageName, int userId,
|
||||
boolean important, boolean newStory) {
|
||||
return new PeopleStoryIconDrawable(headDrawable, getAppBadge(packageName, userId),
|
||||
mIconBitmapSize, mImportantConversationColor, important, mIconSize, mDensity,
|
||||
mAccentColor, newStory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom drawable which overlays a badge drawable on a head icon (conversation/person avatar),
|
||||
* with decorations indicating Important conversations and having a New Story.
|
||||
*/
|
||||
public static class PeopleStoryIconDrawable extends Drawable {
|
||||
private float mFullIconSize;
|
||||
private Drawable mAvatar;
|
||||
private Drawable mBadgeIcon;
|
||||
private int mIconSize;
|
||||
private Paint mPriorityRingPaint;
|
||||
private boolean mShowImportantRing;
|
||||
private boolean mShowStoryRing;
|
||||
private Paint mStoryPaint;
|
||||
private float mDensity;
|
||||
|
||||
PeopleStoryIconDrawable(Drawable avatar,
|
||||
Drawable badgeIcon,
|
||||
int iconSize,
|
||||
@ColorInt int ringColor,
|
||||
boolean showImportantRing, float fullIconSize, float density,
|
||||
@ColorInt int accentColor, boolean showStoryRing) {
|
||||
mAvatar = avatar;
|
||||
mBadgeIcon = badgeIcon;
|
||||
mIconSize = iconSize;
|
||||
mShowImportantRing = showImportantRing;
|
||||
mPriorityRingPaint = new Paint();
|
||||
mPriorityRingPaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||
mPriorityRingPaint.setColor(ringColor);
|
||||
mShowStoryRing = showStoryRing;
|
||||
mStoryPaint = new Paint();
|
||||
mStoryPaint.setStyle(Paint.Style.STROKE);
|
||||
mStoryPaint.setColor(accentColor);
|
||||
mFullIconSize = fullIconSize;
|
||||
mDensity = density;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return mIconSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return mIconSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
final Rect bounds = getBounds();
|
||||
final int minBound = Math.min(bounds.height(), bounds.width());
|
||||
// Scale head icon and app icon to our canvas.
|
||||
float scale = minBound / mFullIconSize;
|
||||
|
||||
int paddingInDp = (int) (PADDING * mDensity);
|
||||
int ringStrokeWidth = (int) (RING_WIDTH * mDensity);
|
||||
mPriorityRingPaint.setStrokeWidth(ringStrokeWidth);
|
||||
mStoryPaint.setStrokeWidth(ringStrokeWidth);
|
||||
|
||||
int scaledFullIconSize = (int) (mFullIconSize * scale);
|
||||
int avatarSize = scaledFullIconSize - (paddingInDp * 2);
|
||||
if (mAvatar != null) {
|
||||
int leftAndTopPadding = paddingInDp;
|
||||
int rightAndBottomPadding = avatarSize + paddingInDp;
|
||||
if (mShowStoryRing) {
|
||||
int headCenter = scaledFullIconSize / 2;
|
||||
canvas.drawCircle(headCenter, headCenter,
|
||||
getRadius(avatarSize, ringStrokeWidth),
|
||||
mStoryPaint);
|
||||
leftAndTopPadding += (ringStrokeWidth + paddingInDp);
|
||||
rightAndBottomPadding -= (ringStrokeWidth + paddingInDp);
|
||||
}
|
||||
mAvatar.setBounds(leftAndTopPadding,
|
||||
leftAndTopPadding,
|
||||
rightAndBottomPadding,
|
||||
rightAndBottomPadding);
|
||||
mAvatar.draw(canvas);
|
||||
} else {
|
||||
Log.w("PeopleStoryIconFactory", "Null avatar icon");
|
||||
}
|
||||
|
||||
// Determine badge size from either the size relative to the head icon, or max size.
|
||||
int maxBadgeSize = (int) (MAX_BADGE_SIZE * mDensity);
|
||||
int badgeSizeRelativeToHead = (int) (avatarSize / 2.4);
|
||||
int badgeSize = Math.min(maxBadgeSize, badgeSizeRelativeToHead);
|
||||
if (mBadgeIcon != null) {
|
||||
int leftAndTopPadding = scaledFullIconSize - badgeSize;
|
||||
int rightAndBottomPadding = scaledFullIconSize;
|
||||
if (mShowImportantRing) {
|
||||
int badgeCenter = leftAndTopPadding + (badgeSize / 2);
|
||||
canvas.drawCircle(badgeCenter, badgeCenter,
|
||||
getRadius(badgeSize, ringStrokeWidth),
|
||||
mPriorityRingPaint);
|
||||
leftAndTopPadding += ringStrokeWidth;
|
||||
rightAndBottomPadding -= ringStrokeWidth;
|
||||
}
|
||||
mBadgeIcon.setBounds(
|
||||
leftAndTopPadding,
|
||||
leftAndTopPadding,
|
||||
rightAndBottomPadding,
|
||||
rightAndBottomPadding);
|
||||
mBadgeIcon.draw(canvas);
|
||||
} else {
|
||||
Log.w("PeopleStoryIconFactory", "Null badge icon");
|
||||
}
|
||||
}
|
||||
|
||||
private int getRadius(int circleWidth, int circleStrokeWidth) {
|
||||
return (circleWidth - circleStrokeWidth) / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
// unimplemented
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter colorFilter) {
|
||||
// unimplemented
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,15 +37,16 @@ public class AppWidgetOptionsHelper {
|
||||
public static final String OPTIONS_PEOPLE_TILE = "options_people_tile";
|
||||
|
||||
/** Sets {@link PeopleSpaceTile} in AppWidgetOptions. */
|
||||
public static void setPeopleTile(AppWidgetManager appWidgetManager, int appWidgetId,
|
||||
public static Bundle setPeopleTile(AppWidgetManager appWidgetManager, int appWidgetId,
|
||||
PeopleSpaceTile tile) {
|
||||
Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
|
||||
if (tile == null) {
|
||||
if (DEBUG) Log.d(TAG, "Requested to store null tile");
|
||||
return;
|
||||
return options;
|
||||
}
|
||||
Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
|
||||
options.putParcelable(OPTIONS_PEOPLE_TILE, tile);
|
||||
appWidgetManager.updateAppWidgetOptions(appWidgetId, options);
|
||||
return options;
|
||||
}
|
||||
|
||||
/** Gets {@link PeopleSpaceTile} from AppWidgetOptions. */
|
||||
|
||||
@@ -217,8 +217,7 @@ public class PeopleSpaceWidgetManager {
|
||||
.setUserName(info.getLabel())
|
||||
.setUserIcon(
|
||||
PeopleSpaceTile.convertDrawableToIcon(mLauncherApps.getShortcutIconDrawable(
|
||||
info, 0))
|
||||
)
|
||||
info, 0)))
|
||||
.setContactUri(uri)
|
||||
.setStatuses(conversation.getStatuses())
|
||||
.setLastInteractionTimestamp(conversation.getLastEventTimestamp())
|
||||
@@ -250,9 +249,12 @@ public class PeopleSpaceWidgetManager {
|
||||
}
|
||||
storedTile = storedTile
|
||||
.toBuilder()
|
||||
// Reset notification content.
|
||||
.setNotificationKey(null)
|
||||
.setNotificationContent(null)
|
||||
.setNotificationDataUri(null)
|
||||
// Reset missed calls category.
|
||||
.setNotificationCategory(null)
|
||||
.build();
|
||||
}
|
||||
updateAppWidgetOptionsAndView(mAppWidgetManager, mContext, appWidgetId, storedTile);
|
||||
@@ -333,6 +335,8 @@ public class PeopleSpaceWidgetManager {
|
||||
addNewWidget(appWidgetId, optionsKey);
|
||||
AppWidgetOptionsHelper.removePeopleTileKey(mAppWidgetManager, appWidgetId);
|
||||
}
|
||||
// Update views for new widget dimensions.
|
||||
updateWidgets(new int[]{appWidgetId});
|
||||
}
|
||||
|
||||
/** Adds{@code tile} mapped to {@code appWidgetId}. */
|
||||
|
||||
@@ -21,15 +21,16 @@ import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_GAME;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_NEW_STORY;
|
||||
import static android.app.people.ConversationStatus.AVAILABILITY_AVAILABLE;
|
||||
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH;
|
||||
|
||||
import static com.android.systemui.people.PeopleSpaceUtils.PACKAGE_NAME;
|
||||
import static com.android.systemui.people.PeopleSpaceUtils.REQUIRED_WIDTH_FOR_MEDIUM;
|
||||
import static com.android.systemui.people.PeopleSpaceUtils.getPeopleTileFromPersistentStorage;
|
||||
import static com.android.systemui.people.widget.AppWidgetOptionsHelper.OPTIONS_PEOPLE_TILE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
@@ -59,6 +60,8 @@ import android.content.pm.LauncherApps;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.net.Uri;
|
||||
@@ -226,6 +229,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private NotificationEntryManager mNotificationEntryManager;
|
||||
|
||||
private Bundle mOptions;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -233,12 +238,12 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
|
||||
|
||||
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
|
||||
Bundle options = new Bundle();
|
||||
options.putParcelable(OPTIONS_PEOPLE_TILE, PERSON_TILE);
|
||||
mOptions = new Bundle();
|
||||
mOptions.putParcelable(OPTIONS_PEOPLE_TILE, PERSON_TILE);
|
||||
|
||||
when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
|
||||
when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT)))
|
||||
.thenReturn(options);
|
||||
.thenReturn(mOptions);
|
||||
when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT)))
|
||||
.thenReturn(new Bundle());
|
||||
|
||||
@@ -252,6 +257,10 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
when(mMockContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
when(mMockContext.getString(R.string.over_timestamp)).thenReturn(
|
||||
mContext.getString(R.string.over_timestamp));
|
||||
Configuration configuration = mock(Configuration.class);
|
||||
Resources resources = mock(Resources.class);
|
||||
when(mMockContext.getResources()).thenReturn(resources);
|
||||
when(resources.getConfiguration()).thenReturn(configuration);
|
||||
when(mPackageManager.getApplicationIcon(anyString())).thenReturn(null);
|
||||
when(mNotificationEntryManager.getVisibleNotifications())
|
||||
.thenReturn(List.of(mNotificationEntry1, mNotificationEntry2, mNotificationEntry3));
|
||||
@@ -665,7 +674,7 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testCreateRemoteViewsWithLastInteractionTime() {
|
||||
RemoteViews views = PeopleSpaceUtils.createRemoteViews(mMockContext,
|
||||
PERSON_TILE_WITHOUT_NOTIFICATION, 0);
|
||||
PERSON_TILE_WITHOUT_NOTIFICATION, 0, mOptions);
|
||||
View result = views.apply(mContext, null);
|
||||
|
||||
TextView name = (TextView) result.findViewById(R.id.name);
|
||||
@@ -676,13 +685,22 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
// No availability.
|
||||
View availability = result.findViewById(R.id.availability);
|
||||
assertEquals(View.GONE, availability.getVisibility());
|
||||
// No new story.
|
||||
View personIcon = result.findViewById(R.id.person_icon_only);
|
||||
View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
|
||||
// Shows person icon.
|
||||
View personIcon = result.findViewById(R.id.person_icon);
|
||||
assertEquals(View.VISIBLE, personIcon.getVisibility());
|
||||
assertEquals(View.GONE, personIconWithStory.getVisibility());
|
||||
// No status.
|
||||
assertThat((View) result.findViewById(R.id.status)).isNull();
|
||||
assertThat((View) result.findViewById(R.id.text_content)).isNull();
|
||||
|
||||
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, REQUIRED_WIDTH_FOR_MEDIUM - 1);
|
||||
RemoteViews smallView = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
PERSON_TILE_WITHOUT_NOTIFICATION, 0, mOptions);
|
||||
View smallResult = smallView.apply(mContext, null);
|
||||
|
||||
// Show name over predefined icon.
|
||||
assertEquals(View.VISIBLE, smallResult.findViewById(R.id.name).getVisibility());
|
||||
assertEquals(View.GONE, smallResult.findViewById(R.id.predefined_icon).getVisibility());
|
||||
// Shows person icon.
|
||||
assertEquals(View.VISIBLE, smallResult.findViewById(R.id.person_icon).getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -694,7 +712,7 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
PERSON_TILE_WITHOUT_NOTIFICATION.getId(),
|
||||
ACTIVITY_GAME).build())).build();
|
||||
RemoteViews views = PeopleSpaceUtils.createRemoteViews(mMockContext,
|
||||
tileWithAvailabilityAndNewStory, 0);
|
||||
tileWithAvailabilityAndNewStory, 0, mOptions);
|
||||
View result = views.apply(mContext, null);
|
||||
|
||||
TextView name = (TextView) result.findViewById(R.id.name);
|
||||
@@ -705,13 +723,23 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
// Has availability.
|
||||
View availability = result.findViewById(R.id.availability);
|
||||
assertEquals(View.VISIBLE, availability.getVisibility());
|
||||
// Has new story.
|
||||
View personIcon = result.findViewById(R.id.person_icon_only);
|
||||
View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
|
||||
assertEquals(View.GONE, personIcon.getVisibility());
|
||||
assertEquals(View.VISIBLE, personIconWithStory.getVisibility());
|
||||
// Has person icon.
|
||||
View personIcon = result.findViewById(R.id.person_icon);
|
||||
assertEquals(View.VISIBLE, personIcon.getVisibility());
|
||||
// No status.
|
||||
assertThat((View) result.findViewById(R.id.status)).isNull();
|
||||
assertThat((View) result.findViewById(R.id.text_content)).isNull();
|
||||
|
||||
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, REQUIRED_WIDTH_FOR_MEDIUM - 1);
|
||||
RemoteViews smallView = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithAvailabilityAndNewStory, 0, mOptions);
|
||||
View smallResult = smallView.apply(mContext, null);
|
||||
|
||||
// Show name rather than game type.
|
||||
assertEquals(View.VISIBLE, smallResult.findViewById(R.id.name).getVisibility());
|
||||
assertEquals(View.GONE, smallResult.findViewById(R.id.predefined_icon).getVisibility());
|
||||
// Has person icon.
|
||||
assertEquals(View.VISIBLE,
|
||||
smallResult.findViewById(R.id.person_icon).getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -723,7 +751,7 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
PERSON_TILE_WITHOUT_NOTIFICATION.getId(),
|
||||
ACTIVITY_BIRTHDAY).build())).build();
|
||||
RemoteViews views = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithStatusTemplate, 0);
|
||||
tileWithStatusTemplate, 0, mOptions);
|
||||
View result = views.apply(mContext, null);
|
||||
|
||||
TextView name = (TextView) result.findViewById(R.id.name);
|
||||
@@ -731,14 +759,25 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
// Has availability.
|
||||
View availability = result.findViewById(R.id.availability);
|
||||
assertEquals(View.VISIBLE, availability.getVisibility());
|
||||
// Has new story.
|
||||
View personIcon = result.findViewById(R.id.person_icon_only);
|
||||
View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
|
||||
assertEquals(View.GONE, personIcon.getVisibility());
|
||||
assertEquals(View.VISIBLE, personIconWithStory.getVisibility());
|
||||
// Has person icon.
|
||||
View personIcon = result.findViewById(R.id.person_icon);
|
||||
assertEquals(View.VISIBLE, personIcon.getVisibility());
|
||||
// Has status text from backup text.
|
||||
TextView statusContent = (TextView) result.findViewById(R.id.status);
|
||||
TextView statusContent = (TextView) result.findViewById(R.id.text_content);
|
||||
assertEquals(statusContent.getText(), mContext.getString(R.string.birthday_status));
|
||||
|
||||
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, REQUIRED_WIDTH_FOR_MEDIUM - 1);
|
||||
RemoteViews smallView = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithStatusTemplate, 0, mOptions);
|
||||
View smallResult = smallView.apply(mContext, null);
|
||||
|
||||
// Show icon instead of name.
|
||||
assertEquals(View.GONE, smallResult.findViewById(R.id.name).getVisibility());
|
||||
assertEquals(View.VISIBLE,
|
||||
smallResult.findViewById(R.id.predefined_icon).getVisibility());
|
||||
// Has person icon.
|
||||
assertEquals(View.VISIBLE,
|
||||
smallResult.findViewById(R.id.person_icon).getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -748,7 +787,7 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
Arrays.asList(GAME_STATUS,
|
||||
NEW_STORY_WITH_AVAILABILITY)).build();
|
||||
RemoteViews views = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithStatusTemplate, 0);
|
||||
tileWithStatusTemplate, 0, mOptions);
|
||||
View result = views.apply(mContext, null);
|
||||
|
||||
TextView name = (TextView) result.findViewById(R.id.name);
|
||||
@@ -756,14 +795,25 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
// Has availability.
|
||||
View availability = result.findViewById(R.id.availability);
|
||||
assertEquals(View.VISIBLE, availability.getVisibility());
|
||||
// Has new story.
|
||||
View personIcon = result.findViewById(R.id.person_icon_only);
|
||||
View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
|
||||
assertEquals(View.GONE, personIcon.getVisibility());
|
||||
assertEquals(View.VISIBLE, personIconWithStory.getVisibility());
|
||||
// Has person icon.
|
||||
View personIcon = result.findViewById(R.id.person_icon);
|
||||
assertEquals(View.VISIBLE, personIcon.getVisibility());
|
||||
// Has status.
|
||||
TextView statusContent = (TextView) result.findViewById(R.id.status);
|
||||
TextView statusContent = (TextView) result.findViewById(R.id.text_content);
|
||||
assertEquals(statusContent.getText(), GAME_DESCRIPTION);
|
||||
|
||||
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, REQUIRED_WIDTH_FOR_MEDIUM - 1);
|
||||
RemoteViews smallView = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithStatusTemplate, 0, mOptions);
|
||||
View smallResult = smallView.apply(mContext, null);
|
||||
|
||||
// Show icon instead of name.
|
||||
assertEquals(View.GONE, smallResult.findViewById(R.id.name).getVisibility());
|
||||
assertEquals(View.VISIBLE,
|
||||
smallResult.findViewById(R.id.predefined_icon).getVisibility());
|
||||
// Has person icon.
|
||||
assertEquals(View.VISIBLE,
|
||||
smallResult.findViewById(R.id.person_icon).getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -774,7 +824,7 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
.setNotificationContent(MISSED_CALL)
|
||||
.build();
|
||||
RemoteViews views = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithMissedCallNotification, 0);
|
||||
tileWithMissedCallNotification, 0, mOptions);
|
||||
View result = views.apply(mContext, null);
|
||||
|
||||
TextView name = (TextView) result.findViewById(R.id.name);
|
||||
@@ -782,16 +832,25 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
// Has availability.
|
||||
View availability = result.findViewById(R.id.availability);
|
||||
assertEquals(View.GONE, availability.getVisibility());
|
||||
// Has new story.
|
||||
View personIcon = result.findViewById(R.id.person_icon_only);
|
||||
View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
|
||||
// Has person icon.
|
||||
View personIcon = result.findViewById(R.id.person_icon);
|
||||
assertEquals(View.VISIBLE, personIcon.getVisibility());
|
||||
assertEquals(View.GONE, personIconWithStory.getVisibility());
|
||||
// Has status.
|
||||
TextView statusContent = (TextView) result.findViewById(R.id.status);
|
||||
// Has missed call notification content.
|
||||
TextView statusContent = (TextView) result.findViewById(R.id.text_content);
|
||||
assertEquals(statusContent.getText(), MISSED_CALL);
|
||||
}
|
||||
|
||||
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, REQUIRED_WIDTH_FOR_MEDIUM - 1);
|
||||
RemoteViews smallView = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithMissedCallNotification, 0, mOptions);
|
||||
View smallResult = smallView.apply(mContext, null);
|
||||
|
||||
// Show icon instead of name.
|
||||
assertEquals(View.GONE, smallResult.findViewById(R.id.name).getVisibility());
|
||||
assertEquals(View.VISIBLE,
|
||||
smallResult.findViewById(R.id.predefined_icon).getVisibility());
|
||||
// Has person icon.
|
||||
assertEquals(View.VISIBLE, smallResult.findViewById(R.id.person_icon).getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRemoteViewsWithNotificationTemplate() {
|
||||
@@ -800,24 +859,35 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
.setStatuses(Arrays.asList(GAME_STATUS,
|
||||
NEW_STORY_WITH_AVAILABILITY)).build();
|
||||
RemoteViews views = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithStatusAndNotification, 0);
|
||||
tileWithStatusAndNotification, 0, mOptions);
|
||||
View result = views.apply(mContext, null);
|
||||
|
||||
TextView name = (TextView) result.findViewById(R.id.name);
|
||||
assertEquals(name.getText(), NAME);
|
||||
TextView subtext = (TextView) result.findViewById(R.id.subtext);
|
||||
assertTrue(subtext.getText().toString().contains("weeks ago"));
|
||||
assertEquals(View.GONE, subtext.getVisibility());
|
||||
// Has availability.
|
||||
View availability = result.findViewById(R.id.availability);
|
||||
assertEquals(View.VISIBLE, availability.getVisibility());
|
||||
// Has new story.
|
||||
View personIcon = result.findViewById(R.id.person_icon_only);
|
||||
View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
|
||||
assertEquals(View.GONE, personIcon.getVisibility());
|
||||
assertEquals(View.VISIBLE, personIconWithStory.getVisibility());
|
||||
// Has person icon.
|
||||
View personIcon = result.findViewById(R.id.person_icon);
|
||||
assertEquals(View.VISIBLE, personIcon.getVisibility());
|
||||
// Has notification content.
|
||||
TextView statusContent = (TextView) result.findViewById(R.id.content);
|
||||
TextView statusContent = (TextView) result.findViewById(R.id.text_content);
|
||||
assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
|
||||
|
||||
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, REQUIRED_WIDTH_FOR_MEDIUM - 1);
|
||||
RemoteViews smallView = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithStatusAndNotification, 0, mOptions);
|
||||
View smallResult = smallView.apply(mContext, null);
|
||||
|
||||
// Show icon instead of name.
|
||||
assertEquals(View.GONE, smallResult.findViewById(R.id.name).getVisibility());
|
||||
assertEquals(View.VISIBLE,
|
||||
smallResult.findViewById(R.id.predefined_icon).getVisibility());
|
||||
// Has person icon.
|
||||
assertEquals(View.VISIBLE,
|
||||
smallResult.findViewById(R.id.person_icon).getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -626,14 +626,6 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
|
||||
mManager.updateWidgets(widgetIdsArray);
|
||||
mClock.advanceTime(MIN_LINGER_DURATION);
|
||||
|
||||
// If we had to fetch Tile from persistent storage, we want to make sure we write it to
|
||||
// options.
|
||||
verify(mAppWidgetManager, times(1))
|
||||
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
|
||||
mBundleArgumentCaptor.capture());
|
||||
Bundle bundle = mBundleArgumentCaptor.getValue();
|
||||
PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
|
||||
assertThat(tile.getId()).isEqualTo(SHORTCUT_ID);
|
||||
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
|
||||
any());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user