Merge "Make the generic "can't call" error message more specific."
diff --git a/res/drawable-hdpi/ic_emergency_number_24.png b/res/drawable-hdpi/ic_emergency_number_24.png
deleted file mode 100644
index d5c0b28..0000000
--- a/res/drawable-hdpi/ic_emergency_number_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_fire_white_24.png b/res/drawable-hdpi/ic_fire_white_24.png
deleted file mode 100644
index 0c0c6ed..0000000
--- a/res/drawable-hdpi/ic_fire_white_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_shield_white_24.png b/res/drawable-hdpi/ic_shield_white_24.png
deleted file mode 100644
index bf23794..0000000
--- a/res/drawable-hdpi/ic_shield_white_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_emergency_number_24.png b/res/drawable-mdpi/ic_emergency_number_24.png
deleted file mode 100644
index 3db2d19..0000000
--- a/res/drawable-mdpi/ic_emergency_number_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_fire_white_24.png b/res/drawable-mdpi/ic_fire_white_24.png
deleted file mode 100644
index de8fda9..0000000
--- a/res/drawable-mdpi/ic_fire_white_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_shield_white_24.png b/res/drawable-mdpi/ic_shield_white_24.png
deleted file mode 100644
index 9a5d958..0000000
--- a/res/drawable-mdpi/ic_shield_white_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_emergency_number_24.png b/res/drawable-xhdpi/ic_emergency_number_24.png
deleted file mode 100644
index b538c02..0000000
--- a/res/drawable-xhdpi/ic_emergency_number_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_fire_white_24.png b/res/drawable-xhdpi/ic_fire_white_24.png
deleted file mode 100644
index 750072e..0000000
--- a/res/drawable-xhdpi/ic_fire_white_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_shield_white_24.png b/res/drawable-xhdpi/ic_shield_white_24.png
deleted file mode 100644
index e886233..0000000
--- a/res/drawable-xhdpi/ic_shield_white_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_emergency_number_24.png b/res/drawable-xxhdpi/ic_emergency_number_24.png
deleted file mode 100644
index 13f253b..0000000
--- a/res/drawable-xxhdpi/ic_emergency_number_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_fire_white_24.png b/res/drawable-xxhdpi/ic_fire_white_24.png
deleted file mode 100644
index 37c6ecd..0000000
--- a/res/drawable-xxhdpi/ic_fire_white_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_shield_white_24.png b/res/drawable-xxhdpi/ic_shield_white_24.png
deleted file mode 100644
index 1621836..0000000
--- a/res/drawable-xxhdpi/ic_shield_white_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_fire_white_24.png b/res/drawable-xxxhdpi/ic_fire_white_24.png
deleted file mode 100644
index fb1d630..0000000
--- a/res/drawable-xxxhdpi/ic_fire_white_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_shield_white_24.png b/res/drawable-xxxhdpi/ic_shield_white_24.png
deleted file mode 100644
index 8b9f129..0000000
--- a/res/drawable-xxxhdpi/ic_shield_white_24.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/btn_emergency_confirm_information.xml b/res/drawable/btn_emergency_confirm_information.xml
new file mode 100644
index 0000000..22b3069
--- /dev/null
+++ b/res/drawable/btn_emergency_confirm_information.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners android:radius="8dp"/>
+ <solid android:color="@color/emergency_shortcut_confirm_button_background_color"/>
+</shape>
\ No newline at end of file
diff --git a/res/drawable/btn_emergency_confirm_shortcuts.xml b/res/drawable/btn_emergency_confirm_shortcuts.xml
new file mode 100644
index 0000000..22b3069
--- /dev/null
+++ b/res/drawable/btn_emergency_confirm_shortcuts.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners android:radius="8dp"/>
+ <solid android:color="@color/emergency_shortcut_confirm_button_background_color"/>
+</shape>
\ No newline at end of file
diff --git a/res/drawable/btn_emergency_information.xml b/res/drawable/btn_emergency_information.xml
new file mode 100644
index 0000000..29b4a7a
--- /dev/null
+++ b/res/drawable/btn_emergency_information.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners android:radius="8dp"/>
+ <!-- White, Opacity 16% -->
+ <stroke android:width="1dp"
+ android:color="#40FFFFFF"/>
+</shape>
\ No newline at end of file
diff --git a/res/drawable/btn_emergency_shortcuts.xml b/res/drawable/btn_emergency_shortcuts.xml
index 063a824..449e4e0 100644
--- a/res/drawable/btn_emergency_shortcuts.xml
+++ b/res/drawable/btn_emergency_shortcuts.xml
@@ -16,4 +16,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="8dp"/>
+ <solid android:color="@color/emergency_shortcut_button_background_color"/>
</shape>
\ No newline at end of file
diff --git a/res/drawable/emergency_shortcuts_divider.xml b/res/drawable/emergency_shortcuts_divider.xml
index 988ffc5..930d563 100644
--- a/res/drawable/emergency_shortcuts_divider.xml
+++ b/res/drawable/emergency_shortcuts_divider.xml
@@ -15,6 +15,6 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <size android:height="1px"/>
- <solid android:color="#33FFFFFF"/>
+ <size android:height="8dp"/>
+ <solid android:color="@android:color/transparent"/>
</shape>
diff --git a/res/drawable/ic_local_fire_department_gm2_24px.xml b/res/drawable/ic_local_fire_department_gm2_24px.xml
new file mode 100644
index 0000000..a99792c
--- /dev/null
+++ b/res/drawable/ic_local_fire_department_gm2_24px.xml
@@ -0,0 +1,28 @@
+<!--
+ Copyright (C) 2018 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">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12.06,3.74c0.26,1.65 1.03,3.21 2.26,4.46c0.53,0.53 1.09,0.95 1.59,1.33c0.38,0.29 0.74,0.55 1.04,0.83c0.3,0.28 0.54,0.55 0.74,0.82l0.03,0.03l0.03,0.03c0.27,0.34 0.52,0.74 0.72,1.15l0.05,0.1c0.02,0.04 0.03,0.07 0.05,0.11l0.02,0.04l0.02,0.04c0.88,2.11 0.31,4.6 -1.4,6.19c-1.45,1.34 -3.35,1.62 -4.69,1.62c-0.42,0 -0.86,-0.03 -1.29,-0.08c-1.87,-0.24 -3.67,-1.45 -4.71,-3.18c-0.31,-0.51 -0.56,-1.08 -0.74,-1.72c-0.11,-0.38 -0.18,-0.79 -0.22,-1.23c0.03,0.05 0.07,0.09 0.1,0.14c0.14,0.2 0.29,0.34 0.38,0.43l0.02,0.02l0.02,0.02c0.53,0.5 1.21,0.78 1.91,0.78c0.2,0 0.72,-0.02 1.17,-0.23c0.99,-0.43 1.63,-1.41 1.63,-2.49c0,-0.37 -0.08,-0.67 -0.14,-0.88l-0.03,-0.13l-0.05,-0.12C9.48,9.01 10.1,5.89 12.06,3.74M13.88,0c-0.06,0 -0.11,0.01 -0.17,0.04c-0.78,0.34 -1.43,0.83 -2.08,1.36C8.37,4.05 7.16,8.51 8.67,12.53c0.03,0.14 0.09,0.29 0.09,0.43c0,0.29 -0.18,0.55 -0.43,0.66c-0.09,0.04 -0.27,0.06 -0.37,0.06c-0.19,0 -0.38,-0.09 -0.53,-0.23c-0.07,-0.07 -0.13,-0.13 -0.19,-0.21C6.2,11.86 5.8,10 6.1,8.28c0.05,-0.29 -0.18,-0.5 -0.41,-0.5c-0.12,0 -0.23,0.05 -0.32,0.16c-1.32,1.72 -1.98,4.03 -1.85,6.2c0.04,0.65 0.14,1.29 0.32,1.92c0.22,0.78 0.54,1.54 0.96,2.23c1.32,2.21 3.65,3.8 6.16,4.11c0.51,0.07 1.03,0.1 1.54,0.1c2.19,0 4.38,-0.62 6.05,-2.15c2.29,-2.12 3.12,-5.49 1.89,-8.43c-0.04,-0.12 -0.1,-0.23 -0.15,-0.35c-0.27,-0.57 -0.6,-1.11 -1,-1.59c-0.3,-0.39 -0.62,-0.75 -0.97,-1.08c-0.82,-0.77 -1.78,-1.32 -2.58,-2.12c-1.63,-1.66 -2.19,-3.99 -1.47,-6.21C14.37,0.28 14.15,0 13.88,0L13.88,0z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12.93,18.32c-0.56,0 -1.12,-0.16 -1.67,-0.49c-0.08,-0.05 -0.13,-0.13 -0.12,-0.22c0,-0.09 0.06,-0.17 0.14,-0.21c0.98,-0.49 1.67,-1.37 1.9,-2.42c0.17,-0.76 0,-1.44 -0.16,-2.09c-0.07,-0.28 -0.13,-0.52 -0.17,-0.78c-0.06,-0.38 -0.09,-0.72 -0.07,-1.03c0,-0.1 0.07,-0.2 0.17,-0.23c0.1,-0.03 0.21,0 0.27,0.08c0.33,0.42 0.73,0.8 1.12,1.16c0.74,0.69 1.49,1.38 1.68,2.35c0.03,0.18 0.05,0.33 0.05,0.47c0.03,0.97 -0.38,1.99 -1.05,2.59c-0.31,0.27 -0.83,0.56 -1.24,0.69C13.5,18.27 13.22,18.32 12.93,18.32z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_local_hospital_gm2_24px.xml b/res/drawable/ic_local_hospital_gm2_24px.xml
new file mode 100644
index 0000000..2e535f2
--- /dev/null
+++ b/res/drawable/ic_local_hospital_gm2_24px.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2018 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">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M19,3H5C3.9,3 3.01,3.9 3.01,5L3,19c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3zM19,19L5,19V5h14V19z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M10.5,17l3,0l0,-3.5l3.5,0l0,-3l-3.5,0l0,-3.5l-3,0l0,3.5l-3.5,0l0,3l3.5,0z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_local_police_gm2_24px.xml b/res/drawable/ic_local_police_gm2_24px.xml
new file mode 100644
index 0000000..c65d0b1
--- /dev/null
+++ b/res/drawable/ic_local_police_gm2_24px.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2018 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">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M19,6.3c0,1.57 0,3.13 0,4.7c0,4.52 -2.98,8.69 -7,9.93C7.98,19.69 5,15.52 5,11V6.3c2.33,-1.04 4.67,-2.07 7,-3.11C14.33,4.23 16.67,5.26 19,6.3zM12,1L3,5v6c0,5.55 3.84,10.74 9,12c5.16,-1.26 9,-6.45 9,-12V5L12,1z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M13.54,9.66l-1.54,-3.64l-1.54,3.65l-3.96,0.34l3,2.59l-0.9,3.87l3.4,-2.05l3.4,2.05l-0.9,-3.88l3,-2.59z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/place_gm2_24px.xml b/res/drawable/place_gm2_24px.xml
new file mode 100644
index 0000000..4fd2274
--- /dev/null
+++ b/res/drawable/place_gm2_24px.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2018 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">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,9m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
+</vector>
\ No newline at end of file
diff --git a/res/layout/emergency_dialer.xml b/res/layout/emergency_dialer.xml
index 7f99664..491b661 100644
--- a/res/layout/emergency_dialer.xml
+++ b/res/layout/emergency_dialer.xml
@@ -38,8 +38,8 @@
android:id="@+id/dialpad_button_container"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:layout_gravity="bottom|end"
- android:layout_margin="@dimen/emergency_dialer_dialpad_button_margin">
+ android:layout_gravity="bottom|center"
+ android:layout_marginBottom="@dimen/emergency_dialer_dialpad_button_margin">
<ImageButton
android:id="@+id/floating_action_button_dialpad"
android:layout_width="@dimen/dialpad_button_width"
diff --git a/res/layout/emergency_information.xml b/res/layout/emergency_information.xml
index c4ab74b..e925479 100644
--- a/res/layout/emergency_information.xml
+++ b/res/layout/emergency_information.xml
@@ -16,62 +16,92 @@
<com.android.phone.EmergencyInfoGroup
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/emergency_info_button"
- android:layout_height="@dimen/emergency_info_button_singleline_height"
+ android:layout_height="@dimen/emergency_info_button_height"
android:layout_width="match_parent"
- android:layout_marginTop="@dimen/emergency_info_button_margin_top">
- <LinearLayout
+ android:layout_marginHorizontal="@dimen/emergency_shortcut_buttons_margin_horizontal"
+ android:layout_marginVertical="@dimen/emergency_info_button_margin_vertical">
+ <FrameLayout
+ android:id="@+id/emergency_info_view"
android:layout_height="match_parent"
android:layout_width="match_parent"
- android:layout_marginEnd="56dp"
- android:orientation="horizontal">
- <FrameLayout
- android:id="@+id/emergency_info_image_container"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_gravity="center_vertical|start"
- android:layout_marginHorizontal="@dimen/emergency_dialer_image_margin_horizontal">
+ android:background="@drawable/btn_emergency_information"
+ android:focusable="true"
+ android:clickable="true" >
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="horizontal">
<ImageView
android:id="@+id/emergency_info_image"
+ android:layout_gravity="center_vertical|start"
+ android:layout_marginStart="@dimen/emergency_dialer_image_margin_start"
+ android:layout_marginEnd="@dimen/emergency_dialer_image_margin_end"
android:layout_height="@dimen/emergency_info_image_height"
android:layout_width="@dimen/emergency_info_image_width"
android:scaleType="centerCrop"/>
- </FrameLayout>
- <LinearLayout
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:orientation="vertical"
- android:layout_gravity="center_vertical">
- <TextView
- android:id="@+id/emergency_info_name"
+ <LinearLayout
android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:includeFontPadding="false"
- android:maxLines="1"
- android:ellipsize="end"
- android:textAppearance="@style/HeadlineTextAppearance"/>
- <TextView
- android:id="@+id/emergency_info_hint"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:maxLines="2"
- android:ellipsize="end"
- android:lineHeight="@dimen/emergency_info_hint_line_height"
- android:alpha="0.7"
- android:textAppearance="@style/SubtitleTextAppearance"
- android:text="@string/emergency_information_hint"/>
+ android:layout_width="match_parent"
+ android:layout_marginEnd="@dimen/emergency_info_text_margin_end"
+ android:orientation="vertical"
+ android:layout_gravity="center_vertical">
+ <TextView
+ android:id="@+id/emergency_info_name"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:includeFontPadding="false"
+ android:maxLines="1"
+ android:ellipsize="end"
+ android:lineHeight="@dimen/emergency_info_name_line_height"
+ android:fontFamily="google-sans"
+ android:textAppearance="@style/HeadlineTextAppearance"/>
+ <TextView
+ android:id="@+id/emergency_info_hint"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:maxLines="2"
+ android:ellipsize="end"
+ android:lineHeight="@dimen/emergency_info_hint_line_height"
+ android:alpha="0.7"
+ android:textAppearance="@style/SubtitleTextAppearance"
+ android:text="@string/emergency_information_hint"/>
+ </LinearLayout>
</LinearLayout>
- </LinearLayout>
+ </FrameLayout>
<FrameLayout
- android:id="@+id/arrow_go_next_container"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_gravity="center_vertical|end"
- android:layout_marginHorizontal="@dimen/emergency_dialer_image_margin_horizontal">
- <ImageView
- android:id="@+id/arrow_go_next"
- android:layout_height="@dimen/emergency_shortcuts_function_icon_height"
- android:layout_width="@dimen/emergency_shortcuts_function_icon_width"
- android:src="@drawable/ic_arrow_go_next_18"/>
+ android:id="@+id/emergency_info_confirm_view"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:background="@drawable/btn_emergency_confirm_information"
+ android:focusable="true"
+ android:clickable="true"
+ android:visibility="invisible" >
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/confirmed_emergency_info_image"
+ android:layout_gravity="center_vertical|start"
+ android:layout_height="@dimen/emergency_info_image_height"
+ android:layout_width="@dimen/emergency_info_image_width"
+ android:layout_marginStart="@dimen/emergency_dialer_image_margin_start"
+ android:layout_marginEnd="@dimen/emergency_dialer_image_margin_end"
+ android:scaleType="centerCrop"/>
+ <TextView
+ android:id="@+id/confirmed_emergency_info"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginEnd="@dimen/emergency_info_text_margin_end"
+ android:includeFontPadding="false"
+ android:maxLines="2"
+ android:ellipsize="end"
+ android:lineHeight="@dimen/confirmed_emergency_info_line_height"
+ android:fontFamily="google-sans"
+ android:textAppearance="@style/PhoneCallHintTextAppearance"
+ android:text="@string/emergency_information_confirm_hint"/>
+ </LinearLayout>
</FrameLayout>
</com.android.phone.EmergencyInfoGroup>
diff --git a/res/layout/emergency_shortcut_button.xml b/res/layout/emergency_shortcut_button.xml
index 6087dba..136db0c 100644
--- a/res/layout/emergency_shortcut_button.xml
+++ b/res/layout/emergency_shortcut_button.xml
@@ -22,20 +22,21 @@
android:id="@+id/emergency_call_number_info_view"
android:layout_height="match_parent"
android:layout_width="match_parent"
- android:background="@color/emergency_shortcut_button_background_color"
+ android:background="@drawable/btn_emergency_shortcuts"
android:focusable="true"
android:clickable="true">
<LinearLayout
android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_marginEnd="@dimen/emergency_info_image_width"
+ android:layout_width="match_parent"
+ android:layout_marginEnd="@dimen/emergency_shortcuts_margin_end"
android:layout_gravity="center_vertical|start"
android:orientation="horizontal">
<FrameLayout
android:layout_height="@dimen/phone_number_type_circle_image_height"
android:layout_width="@dimen/phone_number_type_circle_image_width"
android:layout_gravity="center_vertical"
- android:layout_marginHorizontal="@dimen/emergency_dialer_image_margin_horizontal"
+ android:layout_marginStart="@dimen/emergency_dialer_image_margin_start"
+ android:layout_marginEnd="@dimen/emergency_dialer_image_margin_end"
android:background="@drawable/phone_type_icon_background">
<ImageView
android:id="@+id/phone_type_icon"
@@ -55,21 +56,24 @@
android:includeFontPadding="false"
android:maxLines="1"
android:ellipsize="end"
- android:textAppearance="@style/HeadlineTextAppearance"/>
+ android:lineHeight="@dimen/phone_number_line_height"
+ android:fontFamily="google-sans"
+ android:textAppearance="@style/PhoneNumberTextAppearance"/>
<TextView
android:id="@+id/phone_number_description"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:alpha="0.8"
+ android:alpha="0.7"
android:maxLines="1"
android:ellipsize="end"
+ android:fontFamily="sans-serif-medium"
android:textAppearance="@style/SubtitleTextAppearance"/>
</LinearLayout>
</LinearLayout>
<FrameLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:layout_marginHorizontal="@dimen/emergency_dialer_image_margin_horizontal"
+ android:layout_marginEnd="@dimen/emergency_dialer_image_margin_end"
android:layout_gravity="center_vertical|end">
<ImageView
android:id="@+id/microphone_icon"
@@ -84,21 +88,22 @@
android:id="@+id/emergency_call_confirm_view"
android:layout_height="match_parent"
android:layout_width="match_parent"
- android:background="@color/emergency_shortcut_confirm_button_background_color"
+ android:background="@drawable/btn_emergency_confirm_shortcuts"
android:focusable="true"
android:clickable="true"
android:visibility="invisible">
<LinearLayout
android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_marginEnd="@dimen/emergency_info_image_width"
+ android:layout_width="match_parent"
+ android:layout_marginEnd="@dimen/emergency_shortcuts_margin_end"
android:layout_gravity="center_vertical|start"
android:gravity="center_vertical"
android:orientation="horizontal">
<FrameLayout
android:layout_height="@dimen/phone_number_type_circle_image_height"
android:layout_width="@dimen/phone_number_type_circle_image_width"
- android:layout_marginHorizontal="@dimen/emergency_dialer_image_margin_horizontal"
+ android:layout_marginStart="@dimen/emergency_dialer_image_margin_start"
+ android:layout_marginEnd="@dimen/emergency_dialer_image_margin_end"
android:background="@drawable/phone_type_icon_background"
android:backgroundTint="@android:color/white">
<ImageView
@@ -119,13 +124,15 @@
android:maxLines="2"
android:ellipsize="end"
android:lineHeight="@dimen/phone_call_hint_line_height"
- android:textAppearance="@style/ShortcutsHintTextAppearance"/>
+ android:fontFamily="google-sans"
+ android:textAppearance="@style/PhoneCallHintTextAppearance"/>
</FrameLayout>
</LinearLayout>
<FrameLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:layout_marginHorizontal="@dimen/emergency_dialer_image_margin_horizontal"
+ android:layout_marginStart="@dimen/emergency_dialer_image_margin_start"
+ android:layout_marginEnd="@dimen/emergency_dialer_image_margin_end"
android:layout_gravity="center_vertical|end">
<ImageView
android:layout_height="@dimen/phone_icon_height"
diff --git a/res/layout/emergency_shortcut_buttons_group.xml b/res/layout/emergency_shortcut_buttons_group.xml
index 619eac6..bafedd1 100644
--- a/res/layout/emergency_shortcut_buttons_group.xml
+++ b/res/layout/emergency_shortcut_buttons_group.xml
@@ -18,13 +18,12 @@
android:id="@+id/emergency_shortcut_buttons_group"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:layout_marginTop="@dimen/emergency_shortcuts_group_margin_top"
android:orientation="vertical">
<FrameLayout
android:id="@+id/emergency_number_title_group"
android:layout_height="@dimen/emergency_number_title_height"
android:layout_width="match_parent"
- android:paddingHorizontal="@dimen/emergency_number_title_group_padding_horizontal">
+ android:layout_marginHorizontal="@dimen/emergency_number_title_group_padding_horizontal">
<FrameLayout
android:id="@+id/emergency_number_title_container"
android:layout_height="wrap_content"
@@ -35,8 +34,10 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="start"
- android:maxLines="1"
+ android:maxLines="2"
android:ellipsize="end"
+ android:lineHeight="@dimen/emergency_number_title_line_height"
+ android:fontFamily="sans-serif-medium"
android:textAppearance="@style/SubtitleTextAppearance"
android:text="@string/single_emergency_number_title"/>
</FrameLayout>
@@ -53,14 +54,15 @@
android:id="@+id/location_icon"
android:layout_width="@dimen/location_image_width"
android:layout_height="@dimen/location_image_height"
- android:src="@drawable/ic_location_on_white_18"/>
+ android:src="@drawable/place_gm2_24px"/>
<TextView
android:id="@+id/location_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:paddingStart="4dp"
- android:maxLines="1"
+ android:layout_marginStart="@dimen/location_text_margin_start"
+ android:maxLines="2"
android:ellipsize="end"
+ android:lineHeight="@dimen/location_text_line_height"
android:textAppearance="@style/SubtitleTextAppearance"/>
</LinearLayout>
</FrameLayout>
@@ -71,7 +73,6 @@
android:layout_marginHorizontal="@dimen/emergency_shortcut_buttons_margin_horizontal"
android:orientation="vertical"
android:divider="@drawable/emergency_shortcuts_divider"
- android:showDividers="middle"
- android:background="@drawable/btn_emergency_shortcuts">
+ android:showDividers="middle">
</LinearLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 7136819..cc6f727 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -54,6 +54,6 @@
<color name="dialer_dialpad_touch_tint">#330288d1</color>
<color name="floating_action_button_touch_tint">#80ffffff</color>
- <color name="emergency_shortcut_button_background_color">#1FFFFFFF</color>
+ <color name="emergency_shortcut_button_background_color">#40FFFFFF</color>
<color name="emergency_shortcut_confirm_button_background_color">#E25142</color>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 97417bd..b657e64 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -115,28 +115,29 @@
<dimen name="emergency_call_warning_size">16sp</dimen>
<!-- Horizontal margin for the image on emergency dialer.-->
- <dimen name="emergency_dialer_image_margin_horizontal">16dp</dimen>
+ <dimen name="emergency_dialer_image_margin_start">20dp</dimen>
+ <dimen name="emergency_dialer_image_margin_end">16dp</dimen>
<!-- Margin of dialpad button -->
- <dimen name="emergency_dialer_dialpad_button_margin">16dp</dimen>
+ <dimen name="emergency_dialer_dialpad_button_margin">40dp</dimen>
<!-- Horizontal margin for button of emergency shortcut. -->
<dimen name="emergency_shortcut_buttons_margin_horizontal">16dp</dimen>
- <!-- Margin top of emergency shortcuts group -->
- <dimen name="emergency_shortcuts_group_margin_top">48dp</dimen>
-
<!-- Horizontal padding for group of emergency number title-->
<dimen name="emergency_number_title_group_padding_horizontal">16dp</dimen>
- <!-- Height and top margin for the emergency information button. -->
- <dimen name="emergency_info_button_singleline_height">72dp</dimen>
- <dimen name="emergency_info_button_margin_top">56dp</dimen>
- <dimen name="emergency_info_button_multiline_height">90dp</dimen>
+ <!-- Height and vertical margin for the emergency information button. -->
+ <dimen name="emergency_info_button_height">96dp</dimen>
+ <dimen name="emergency_info_button_margin_vertical">56dp</dimen>
+ <dimen name="emergency_info_button_fix_margin_vertical">40dp</dimen>
+
+ <!-- Margin for the emergency information button text. -->
+ <dimen name="emergency_info_text_margin_end">20dp</dimen>
<!-- The height and width for the image of emergency information. -->
- <dimen name="emergency_info_image_height">56dp</dimen>
- <dimen name="emergency_info_image_width">56dp</dimen>
+ <dimen name="emergency_info_image_height">40dp</dimen>
+ <dimen name="emergency_info_image_width">40dp</dimen>
<!-- The height and width for the function icon of emergency shortcuts. -->
<dimen name="emergency_shortcuts_function_icon_height">24dp</dimen>
@@ -150,11 +151,11 @@
<dimen name="emergency_number_title_height">48dp</dimen>
<!-- The height and width for the image of location info.-->
- <dimen name="location_image_height">15dp</dimen>
- <dimen name="location_image_width">15dp</dimen>
+ <dimen name="location_image_height">16dp</dimen>
+ <dimen name="location_image_width">16dp</dimen>
<!-- The height for button of emergency shortcut. -->
- <dimen name="emergency_shortcut_button_height">80dp</dimen>
+ <dimen name="emergency_shortcut_button_height">96dp</dimen>
<!-- The height and width for the circle image of phone number type.-->
<dimen name="phone_number_type_circle_image_height">40dp</dimen>
@@ -168,9 +169,30 @@
<dimen name="phone_icon_height">24dp</dimen>
<dimen name="phone_icon_width">24dp</dimen>
- <!-- The line height for emergency info hint and phone call hint.-->
- <dimen name="emergency_info_hint_line_height">17dp</dimen>
- <dimen name="phone_call_hint_line_height">20dp</dimen>
+ <!-- Margin for the emergency shortcut button.-->
+ <dimen name="emergency_shortcuts_margin_end">60dp</dimen>
+
+ <!-- The line height and margin start for location text.-->
+ <dimen name="location_text_line_height">20sp</dimen>
+ <dimen name="location_text_margin_start">4dp</dimen>
+
+ <!-- The line height for emergency number title.-->
+ <dimen name="emergency_number_title_line_height">20sp</dimen>
+
+ <!-- The line height for phone number.-->
+ <dimen name="phone_number_line_height">40sp</dimen>
+
+ <!-- The line height for phone call hint.-->
+ <dimen name="phone_call_hint_line_height">24sp</dimen>
+
+ <!-- The line height for emergency info name.-->
+ <dimen name="emergency_info_name_line_height">28sp</dimen>
+
+ <!-- The line height for emergency info hint.-->
+ <dimen name="emergency_info_hint_line_height">20sp</dimen>
+
+ <!-- The line height for confirmed emergency info.-->
+ <dimen name="confirmed_emergency_info_line_height">24sp</dimen>
<!-- The width for emergency number title container.-->
<dimen name="emergency_number_title_container_width">210dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0233555..9e55501 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -519,7 +519,15 @@
<!-- Mobile network 4G title [CHAR LIMIT=30] -->
<string name="enhanced_4g_lte_mode_title">Enhanced 4G LTE Mode</string>
<!-- Carrier variant of Enhaced 4G LTE Mode title. [CHAR LIMIT=50] -->
- <string name="enhanced_4g_lte_mode_title_variant">Advanced Calling</string>
+ <string-array name="enhanced_4g_lte_mode_title_variant">
+ <!-- 0: Default -->
+ <item>@string/enhanced_4g_lte_mode_title</item>
+ <!-- 1: Verizon -->
+ <item>Advanced Calling</item>
+ <!-- 2: O2 UK -->
+ <item>4G Calling</item>
+ </string-array>
+
<!-- Mobile network 4G summary [CHAR LIMIT=80] -->
<string name="enhanced_4g_lte_mode_summary">Use LTE services to improve voice and other communications (recommended)</string>
@@ -1128,6 +1136,8 @@
<string name="emergency_information_hint">Emergency information</string>
<!-- Hint for the owner of emergency information -->
<string name="emergency_information_owner_hint">Owner</string>
+ <!-- Hint for confirm the emergency information -->
+ <string name="emergency_information_confirm_hint">Tap again to view info</string>
<!-- Dialog title for the "radio enable" UI for emergency calls -->
<string name="emergency_enable_radio_dialog_title">Emergency call</string>
<!-- Title for the emergency dialpad UI -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 73b5c40..6093cee 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -316,13 +316,22 @@
<style name="HeadlineTextAppearance">
<item name="android:textColor">@android:color/white</item>
- <item name="android:textSize">24sp</item>
+ <item name="android:textSize">22sp</item>
</style>
<style name="SubtitleTextAppearance" parent="@style/HeadlineTextAppearance">
<item name="android:textSize">14sp</item>
</style>
+ <style name="PhoneNumberTextAppearance">
+ <item name="android:textColor">@android:color/white</item>
+ <item name="android:textSize">32sp</item>
+ </style>
+
+ <style name="PhoneCallHintTextAppearance" parent="@style/PhoneNumberTextAppearance">
+ <item name="android:textSize">18sp</item>
+ </style>
+
<style name="ShortcutsHintTextAppearance" parent="@style/HeadlineTextAppearance">
<item name="android:textSize">16sp</item>
</style>
diff --git a/src/com/android/phone/CellInfoUtil.java b/src/com/android/phone/CellInfoUtil.java
index 462cafe..8272029 100644
--- a/src/com/android/phone/CellInfoUtil.java
+++ b/src/com/android/phone/CellInfoUtil.java
@@ -127,6 +127,35 @@
return oi;
}
+ /**
+ * Creates a CellInfo object from OperatorInfo. GsmCellInfo is used here only because
+ * operatorInfo does not contain technology type while CellInfo is an abstract object that
+ * requires to specify technology type. It doesn't matter which CellInfo type to use here, since
+ * we only want to wrap the operator info and PLMN to a CellInfo object.
+ */
+ public static CellInfo convertOperatorInfoToCellInfo(OperatorInfo operatorInfo) {
+ String operatorNumeric = operatorInfo.getOperatorNumeric();
+ String mcc = null;
+ String mnc = null;
+ if (operatorNumeric != null && operatorNumeric.matches("^[0-9]{5,6}$")) {
+ mcc = operatorNumeric.substring(0, 3);
+ mnc = operatorNumeric.substring(3);
+ }
+ CellIdentityGsm cig = new CellIdentityGsm(
+ Integer.MAX_VALUE /* lac */,
+ Integer.MAX_VALUE /* cid */,
+ Integer.MAX_VALUE /* arfcn */,
+ Integer.MAX_VALUE /* bsic */,
+ mcc,
+ mnc,
+ operatorInfo.getOperatorAlphaLong(),
+ operatorInfo.getOperatorAlphaShort());
+
+ CellInfoGsm ci = new CellInfoGsm();
+ ci.setCellIdentity(cig);
+ return ci;
+ }
+
/** Checks whether the network operator is forbidden. */
public static boolean isForbidden(CellInfo cellInfo, List<String> forbiddenPlmns) {
String plmn = CellInfoUtil.getOperatorInfoFromCellInfo(cellInfo).getOperatorNumeric();
diff --git a/src/com/android/phone/EccShortcutAdapter.java b/src/com/android/phone/EccShortcutAdapter.java
index deeb82f..e14b90a 100644
--- a/src/com/android/phone/EccShortcutAdapter.java
+++ b/src/com/android/phone/EccShortcutAdapter.java
@@ -186,15 +186,15 @@
switch (type) {
case POLICE:
description = mPoliceDescription;
- material.iconRes = R.drawable.ic_shield_white_24;
+ material.iconRes = R.drawable.ic_local_police_gm2_24px;
break;
case AMBULANCE:
description = mAmbulanceDescription;
- material.iconRes = R.drawable.ic_emergency_number_24;
+ material.iconRes = R.drawable.ic_local_hospital_gm2_24px;
break;
case FIRE:
description = mFireDescription;
- material.iconRes = R.drawable.ic_fire_white_24;
+ material.iconRes = R.drawable.ic_local_fire_department_gm2_24px;
break;
default:
// ignore unknown types
@@ -204,7 +204,7 @@
material.description = description;
} else {
// concatenate multiple types
- material.iconRes = R.drawable.ic_emergency_number_24;
+ material.iconRes = R.drawable.ic_local_hospital_gm2_24px;
material.description = context.getString(R.string.description_concat_format,
material.description, description);
}
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index 66701d5..1fbbd33 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -108,17 +108,12 @@
* moved into a shared base class that would live in the framework?
* Or could we figure out some way to move *this* class into apps/Contacts
* also?
- *
- * TODO: Implement emergency dialer shortcut.
- * Emergency dialer shortcut offer a local emergency number list. Directly clicking a call button
- * to place an emergency phone call without entering numbers from dialpad.
- * TODO item:
- * 1.integrate emergency phone number table.
*/
public class EmergencyDialer extends Activity implements View.OnClickListener,
View.OnLongClickListener, View.OnKeyListener, TextWatcher,
DialpadKeyButton.OnPressedListener, ColorExtractor.OnColorsChangedListener,
- EmergencyShortcutButton.OnConfirmClickListener, SensorEventListener {
+ EmergencyShortcutButton.OnConfirmClickListener, SensorEventListener,
+ EmergencyInfoGroup.OnConfirmClickListener {
private class MetricsWriter {
// Metrics constants indicating the entry type that user opened emergency dialer.
@@ -244,6 +239,8 @@
private EmergencyActionGroup mEmergencyActionGroup;
+ private EmergencyInfoGroup mEmergencyInfoGroup;
+
// close activity when screen turns off
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -451,6 +448,8 @@
mEmergencyActionGroup = (EmergencyActionGroup) findViewById(R.id.emergency_action_group);
+ mEmergencyInfoGroup = (EmergencyInfoGroup) findViewById(R.id.emergency_info_button);
+
if (mAreEmergencyDialerShortcutsEnabled) {
mEccInfoHelper = new EccInfoHelper(new IsoToEccProtobufRepository());
setupEmergencyShortcutsView();
@@ -606,6 +605,17 @@
}
@Override
+ public void onConfirmClick(EmergencyInfoGroup button) {
+ if (button == null) return;
+
+ mUserActions |= MetricsWriter.USER_ACTION_OPEN_EMERGENCY_INFO;
+ Intent intent = (Intent) button.getTag(R.id.tag_intent);
+ if (intent != null) {
+ startActivity(intent);
+ }
+ }
+
+ @Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.deleteButton: {
@@ -629,14 +639,6 @@
switchView(mDialpadView, mEmergencyShortcutView, true);
return;
}
- case R.id.emergency_info_button: {
- mUserActions |= MetricsWriter.USER_ACTION_OPEN_EMERGENCY_INFO;
- Intent intent = (Intent) view.getTag(R.id.tag_intent);
- if (intent != null) {
- startActivity(intent);
- }
- return;
- }
}
}
@@ -1099,8 +1101,7 @@
final View dialpadButton = findViewById(R.id.floating_action_button_dialpad);
dialpadButton.setOnClickListener(this);
- final View emergencyInfoButton = findViewById(R.id.emergency_info_button);
- emergencyInfoButton.setOnClickListener(this);
+ mEmergencyInfoGroup.setOnConfirmClickListener(this);
// EmergencyActionGroup is replaced by EmergencyInfoGroup.
mEmergencyActionGroup.setVisibility(View.GONE);
@@ -1179,10 +1180,15 @@
shortcutButtonContainer.addView(button);
}
- // update emergency numbers title for numerous buttons.
+ // Update emergency numbers title for numerous buttons.
if (mEmergencyShortcutButtonList.size() > 1) {
emergencyNumberTitle.setText(getString(
R.string.numerous_emergency_numbers_title));
+ // Update mEmergencyInfoGroup margin to avoid UI overlay when
+ // emergency shortcut button more than 2.
+ if (mEmergencyShortcutButtonList.size() > 2) {
+ mEmergencyInfoGroup.updateLayoutMargin();
+ }
} else {
emergencyNumberTitle.setText(getText(R.string.single_emergency_number_title));
}
@@ -1205,6 +1211,7 @@
*/
private void onPreTouchEvent(MotionEvent event) {
mEmergencyActionGroup.onPreTouchEvent(event);
+ mEmergencyInfoGroup.onPreTouchEvent(event);
if (mEmergencyShortcutButtonList != null) {
for (EmergencyShortcutButton button : mEmergencyShortcutButtonList) {
@@ -1218,6 +1225,7 @@
*/
private void onPostTouchEvent(MotionEvent event) {
mEmergencyActionGroup.onPostTouchEvent(event);
+ mEmergencyInfoGroup.onPostTouchEvent(event);
if (mEmergencyShortcutButtonList != null) {
for (EmergencyShortcutButton button : mEmergencyShortcutButtonList) {
diff --git a/src/com/android/phone/EmergencyInfoGroup.java b/src/com/android/phone/EmergencyInfoGroup.java
index d0dc322..5c01834 100644
--- a/src/com/android/phone/EmergencyInfoGroup.java
+++ b/src/com/android/phone/EmergencyInfoGroup.java
@@ -16,6 +16,8 @@
package com.android.phone;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
@@ -27,7 +29,10 @@
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -44,23 +49,60 @@
* EmergencyInfoGroup display user icon and user name. And it is an entry point to
* Emergency Information.
*/
-public class EmergencyInfoGroup extends FrameLayout {
- private ImageView mEmergencyInfoImage;
+public class EmergencyInfoGroup extends FrameLayout implements View.OnClickListener {
+ // Time to hide view of confirmation.
+ private static final long HIDE_DELAY_MS = 3000;
+ private static final int[] ICON_VIEWS =
+ {R.id.emergency_info_image, R.id.confirmed_emergency_info_image};
+
private TextView mEmergencyInfoName;
- private TextView mEmergencyInfoHint;
private View mEmergencyInfoButton;
+ private View mEmergencyInfoConfirmButton;
+
+ private MotionEvent mPendingTouchEvent;
+ private OnConfirmClickListener mOnConfirmClickListener;
+
+ private boolean mConfirmViewHiding;
public EmergencyInfoGroup(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
+ /**
+ * Interface definition for a callback to be invoked when the view of confirmation on emergency
+ * info button is clicked.
+ */
+ public interface OnConfirmClickListener {
+ /**
+ * Called when the view of confirmation on emergency info button has been clicked.
+ *
+ * @param button The shortcut button that was clicked.
+ */
+ void onConfirmClick(EmergencyInfoGroup button);
+ }
+
+ /**
+ * Register a callback {@link OnConfirmClickListener} to be invoked when view of confirmation
+ * is clicked.
+ *
+ * @param onConfirmClickListener The callback that will run.
+ */
+ public void setOnConfirmClickListener(OnConfirmClickListener onConfirmClickListener) {
+ mOnConfirmClickListener = onConfirmClickListener;
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mEmergencyInfoButton = findViewById(R.id.emergency_info_button);
- mEmergencyInfoImage = (ImageView) findViewById(R.id.emergency_info_image);
+ mEmergencyInfoButton = findViewById(R.id.emergency_info_view);
mEmergencyInfoName = (TextView) findViewById(R.id.emergency_info_name);
- mEmergencyInfoHint = (TextView) findViewById(R.id.emergency_info_hint);
+
+ mEmergencyInfoConfirmButton = findViewById(R.id.emergency_info_confirm_view);
+
+ mEmergencyInfoButton.setOnClickListener(this);
+ mEmergencyInfoConfirmButton.setOnClickListener(this);
+
+ mConfirmViewHiding = true;
}
@Override
@@ -71,12 +113,6 @@
}
}
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- updateLayoutHeight();
- }
-
private void setupButtonInfo() {
List<ResolveInfo> infos;
@@ -92,8 +128,8 @@
final String packageName = infos.get(0).activityInfo.packageName;
final Intent intent = new Intent(TelephonyManager.ACTION_EMERGENCY_ASSISTANCE)
.setPackage(packageName);
- mEmergencyInfoButton.setTag(R.id.tag_intent, intent);
- mEmergencyInfoImage.setImageDrawable(getCircularUserIcon());
+ setTag(R.id.tag_intent, intent);
+ setUserIcon();
visible = true;
}
@@ -102,6 +138,13 @@
setVisibility(visible ? View.VISIBLE : View.GONE);
}
+ private void setUserIcon() {
+ for (int iconView : ICON_VIEWS) {
+ ImageView userIcon = findViewById(iconView);
+ userIcon.setImageDrawable(getCircularUserIcon());
+ }
+ }
+
/**
* Get user icon.
*
@@ -134,15 +177,124 @@
R.string.emergency_information_owner_hint) : userName;
}
- private void updateLayoutHeight() {
+ /**
+ * Called by the activity before a touch event is dispatched to the view hierarchy.
+ */
+ public void onPreTouchEvent(MotionEvent event) {
+ mPendingTouchEvent = event;
+ }
+
+ /**
+ * Called by the activity after a touch event is dispatched to the view hierarchy.
+ */
+ public void onPostTouchEvent(MotionEvent event) {
+ // Hide the confirmation button if a touch event was delivered to the activity but not to
+ // this view.
+ if (mPendingTouchEvent != null) {
+ hideSelectedButton();
+ }
+ mPendingTouchEvent = null;
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ boolean handled = super.dispatchTouchEvent(event);
+ if (mPendingTouchEvent == event && handled) {
+ mPendingTouchEvent = null;
+ }
+ return handled;
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.emergency_info_view:
+ if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
+ if (mOnConfirmClickListener != null) {
+ mOnConfirmClickListener.onConfirmClick(this);
+ }
+ } else {
+ revealSelectedButton();
+ }
+ break;
+ case R.id.emergency_info_confirm_view:
+ if (mOnConfirmClickListener != null) {
+ mOnConfirmClickListener.onConfirmClick(this);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void revealSelectedButton() {
+ mConfirmViewHiding = false;
+
+ mEmergencyInfoConfirmButton.setVisibility(View.VISIBLE);
+ int centerX = mEmergencyInfoButton.getLeft() + mEmergencyInfoButton.getWidth() / 2;
+ int centerY = mEmergencyInfoButton.getTop() + mEmergencyInfoButton.getHeight() / 2;
+ Animator reveal = ViewAnimationUtils.createCircularReveal(
+ mEmergencyInfoConfirmButton,
+ centerX,
+ centerY,
+ 0,
+ Math.max(centerX, mEmergencyInfoConfirmButton.getWidth() - centerX)
+ + Math.max(centerY, mEmergencyInfoConfirmButton.getHeight() - centerY));
+ reveal.start();
+
+ postDelayed(mCancelSelectedButtonRunnable, HIDE_DELAY_MS);
+ mEmergencyInfoConfirmButton.requestFocus();
+ }
+
+ private void hideSelectedButton() {
+ if (mConfirmViewHiding || mEmergencyInfoConfirmButton.getVisibility() != VISIBLE) {
+ return;
+ }
+
+ mConfirmViewHiding = true;
+
+ removeCallbacks(mCancelSelectedButtonRunnable);
+ int centerX =
+ mEmergencyInfoConfirmButton.getLeft() + mEmergencyInfoConfirmButton.getWidth() / 2;
+ int centerY =
+ mEmergencyInfoConfirmButton.getTop() + mEmergencyInfoConfirmButton.getHeight() / 2;
+ Animator reveal = ViewAnimationUtils.createCircularReveal(
+ mEmergencyInfoConfirmButton,
+ centerX,
+ centerY,
+ Math.max(centerX, mEmergencyInfoButton.getWidth() - centerX)
+ + Math.max(centerY, mEmergencyInfoButton.getHeight() - centerY),
+ 0);
+ reveal.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mEmergencyInfoConfirmButton.setVisibility(INVISIBLE);
+ }
+ });
+ reveal.start();
+
+ mEmergencyInfoButton.requestFocus();
+ }
+
+ private final Runnable mCancelSelectedButtonRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (!isAttachedToWindow()) return;
+ hideSelectedButton();
+ }
+ };
+
+ /**
+ * Update layout margin when emergency shortcut button more than 2.
+ */
+ public void updateLayoutMargin() {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) getLayoutParams();
- // Update height if mEmergencyInfoHint text line more than 1.
- // EmergencyInfoGroup max line is 2, eclipse type "end" will be adopt if string too long.
- params.height =
- mEmergencyInfoHint.getLineCount() > 1 ? getResources().getDimensionPixelSize(
- R.dimen.emergency_info_button_multiline_height)
- : getResources().getDimensionPixelSize(
- R.dimen.emergency_info_button_singleline_height);
+
+ params.topMargin = getResources().getDimensionPixelSize(
+ R.dimen.emergency_info_button_fix_margin_vertical);
+ params.bottomMargin = getResources().getDimensionPixelSize(
+ R.dimen.emergency_info_button_fix_margin_vertical);
+
setLayoutParams(params);
}
}
\ No newline at end of file
diff --git a/src/com/android/phone/GsmUmtsOptions.java b/src/com/android/phone/GsmUmtsOptions.java
index a3f5cfb..3e45173 100644
--- a/src/com/android/phone/GsmUmtsOptions.java
+++ b/src/com/android/phone/GsmUmtsOptions.java
@@ -54,7 +54,7 @@
private PreferenceScreen mPrefScreen;
public GsmUmtsOptions(PreferenceFragment prefFragment, PreferenceScreen prefScreen,
- final int subId, INetworkQueryService queryService) {
+ final int subId) {
final Context context = prefFragment.getContext();
mPrefFragment = prefFragment;
mPrefScreen = prefScreen;
@@ -68,12 +68,12 @@
mNetworkOperator.initialize();
- update(subId, queryService);
+ update(subId);
}
- // Unlike mPrefFragment or mPrefScreen, subId or queryService may change during lifecycle of
- // GsmUmtsOptions. When that happens, we update GsmUmtsOptions with new parameters.
- protected void update(final int subId, INetworkQueryService queryService) {
+ // Unlike mPrefFragment or mPrefScreen, subId may change during lifecycle of GsmUmtsOptions.
+ // When that happens, we update GsmUmtsOptions with new parameters.
+ protected void update(final int subId) {
boolean addAPNExpand = true;
boolean addNetworkOperatorsCategory = true;
boolean addCarrierSettings = true;
@@ -151,7 +151,7 @@
if (addNetworkOperatorsCategory) {
mPrefScreen.addPreference(mNetworkOperator);
- mNetworkOperator.update(subId, queryService);
+ mNetworkOperator.update(subId);
} else {
mPrefScreen.removePreference(mNetworkOperator);
}
diff --git a/src/com/android/phone/MobileDataPreference.java b/src/com/android/phone/MobileDataPreference.java
index 4e82f20..e1ceab0 100644
--- a/src/com/android/phone/MobileDataPreference.java
+++ b/src/com/android/phone/MobileDataPreference.java
@@ -63,6 +63,11 @@
super(context, attrs, com.android.internal.R.attr.switchPreferenceStyle);
}
+ // Must be called to avoid binder leakage.
+ void dispose() {
+ mListener.setListener(false, mSubId, getContext());
+ }
+
@Override
protected void onRestoreInstanceState(Parcelable s) {
CellDataState state = (CellDataState) s;
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index f65250d..3d37c4d 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -24,12 +24,10 @@
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
@@ -38,7 +36,6 @@
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IBinder;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.SystemProperties;
@@ -77,7 +74,6 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
-import com.android.phone.settings.PhoneAccountSettingsFragment;
import com.android.settingslib.RestrictedLockUtils;
import java.util.ArrayList;
@@ -108,6 +104,9 @@
private static final String KEY_ENABLE_ESIM_UI_BY_DEFAULT =
"esim.enable_esim_system_ui_by_default";
+ private static final String LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT =
+ "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
+
private enum TabState {
NO_TABS, UPDATE, DO_NOTHING
}
@@ -171,8 +170,8 @@
boolean isWifiCallingEnabled;
if (simCallManager != null) {
- Intent intent = PhoneAccountSettingsFragment
- .buildPhoneAccountConfigureIntent(context, simCallManager);
+ Intent intent = MobileNetworkSettings.buildPhoneAccountConfigureIntent(
+ context, simCallManager);
PackageManager pm = context.getPackageManager();
isWifiCallingEnabled = intent != null
&& !pm.queryIntentActivities(intent, 0 /* flags */).isEmpty();
@@ -291,6 +290,47 @@
return isImsServiceStateReady;
}
+
+ private static Intent buildPhoneAccountConfigureIntent(
+ Context context, PhoneAccountHandle accountHandle) {
+ Intent intent = buildConfigureIntent(
+ context, accountHandle, TelecomManager.ACTION_CONFIGURE_PHONE_ACCOUNT);
+
+ if (intent == null) {
+ // If the new configuration didn't work, try the old configuration intent.
+ intent = buildConfigureIntent(
+ context, accountHandle, LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT);
+ if (intent != null) {
+ Log.w(MobileNetworkFragment.LOG_TAG,
+ "Phone account using old configuration intent: " + accountHandle);
+ }
+ }
+ return intent;
+ }
+
+ private static Intent buildConfigureIntent(
+ Context context, PhoneAccountHandle accountHandle, String actionStr) {
+ if (accountHandle == null || accountHandle.getComponentName() == null
+ || TextUtils.isEmpty(accountHandle.getComponentName().getPackageName())) {
+ return null;
+ }
+
+ // Build the settings intent.
+ Intent intent = new Intent(actionStr);
+ intent.setPackage(accountHandle.getComponentName().getPackageName());
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, accountHandle);
+
+ // Check to see that the phone account package can handle the setting intent.
+ PackageManager pm = context.getPackageManager();
+ List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0);
+ if (resolutions.size() == 0) {
+ intent = null; // set no intent if the package cannot handle it.
+ }
+
+ return intent;
+ }
+
public static class MobileNetworkFragment extends PreferenceFragment implements
Preference.OnPreferenceChangeListener, RoamingDialogFragment.RoamingDialogListener {
@@ -426,53 +466,6 @@
private final PhoneCallStateListener mPhoneStateListener = new PhoneCallStateListener();
- /**
- * Service connection code for the NetworkQueryService.
- * Handles the work of binding to a local object so that we can make
- * the appropriate service calls.
- */
-
- /** Local service interface */
- private INetworkQueryService mNetworkQueryService = null;
-
- private void setNetworkQueryService() {
- mButtonNetworkSelect = (NetworkSelectListPreference) getPreferenceScreen()
- .findPreference(NetworkOperators.BUTTON_NETWORK_SELECT_KEY);
- if (mButtonNetworkSelect != null) {
- mButtonNetworkSelect.setNetworkQueryService(mNetworkQueryService);
- }
-
- }
- /** Service connection */
- private final ServiceConnection mNetworkQueryServiceConnection = new ServiceConnection() {
-
- /** Handle the task of binding the local object to the service */
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) log("connection created, binding local service.");
- mNetworkQueryService = ((NetworkQueryService.LocalBinder) service).getService();
- setNetworkQueryService();
- }
-
- /** Handle the task of cleaning up the local binding */
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) log("connection disconnected, cleaning local binding.");
- mNetworkQueryService = null;
- setNetworkQueryService();
- }
- };
-
- private void bindNetworkQueryService() {
- getContext().startService(new Intent(getContext(), NetworkQueryService.class));
- getContext().bindService(new Intent(getContext(), NetworkQueryService.class).setAction(
- NetworkQueryService.ACTION_LOCAL_BINDER),
- mNetworkQueryServiceConnection, Context.BIND_AUTO_CREATE);
- }
-
- private void unbindNetworkQueryService() {
- // unbind the service.
- getContext().unbindService(mNetworkQueryServiceConnection);
- }
-
@Override
public void onPositiveButtonClick(DialogFragment dialog) {
mTelephonyManager.setDataRoamingEnabled(true);
@@ -800,8 +793,6 @@
mExpandAdvancedFields = true;
}
- bindNetworkQueryService();
-
addPreferencesFromResource(R.xml.network_setting_fragment);
mButton4glte = (SwitchPreference)findPreference(BUTTON_4G_LTE_KEY);
@@ -904,8 +895,10 @@
@Override
public void onDestroy() {
- unbindNetworkQueryService();
super.onDestroy();
+ if (mMobileDataPref != null) {
+ mMobileDataPref.dispose();
+ }
}
@Override
@@ -1077,7 +1070,7 @@
if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
updateCdmaOptions(this, prefSet, mSubId);
} else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
- updateGsmUmtsOptions(this, prefSet, phoneSubId, mNetworkQueryService);
+ updateGsmUmtsOptions(this, prefSet, phoneSubId);
} else {
throw new IllegalStateException("Unexpected phone type: " + phoneType);
}
@@ -1093,7 +1086,7 @@
mButtonPreferredNetworkMode.setOnPreferenceChangeListener(this);
updateCdmaOptions(this, prefSet, mSubId);
- updateGsmUmtsOptions(this, prefSet, phoneSubId, mNetworkQueryService);
+ updateGsmUmtsOptions(this, prefSet, phoneSubId);
} else {
prefSet.removePreference(mButtonPreferredNetworkMode);
updateEnabledNetworksEntries();
@@ -1161,15 +1154,19 @@
* but you do need to remember that this all needs to work when subscriptions
* change dynamically such as when hot swapping sims.
*/
- boolean useVariant4glteTitle = carrierConfig.getBoolean(
- CarrierConfigManager.KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL);
- int enhanced4glteModeTitleId = useVariant4glteTitle ?
- R.string.enhanced_4g_lte_mode_title_variant :
- R.string.enhanced_4g_lte_mode_title;
+ int variant4glteTitleIndex = carrierConfig.getInt(
+ CarrierConfigManager.KEY_ENHANCED_4G_LTE_TITLE_VARIANT_INT);
+ CharSequence[] variantTitles = getContext().getResources()
+ .getTextArray(R.array.enhanced_4g_lte_mode_title_variant);
+ // Default index 0 indicates the default title string
+ CharSequence enhanced4glteModeTitle = variantTitles[0];
+ if (variant4glteTitleIndex >= 0 && variant4glteTitleIndex < variantTitles.length) {
+ enhanced4glteModeTitle = variantTitles[variant4glteTitleIndex];
+ }
mOnlyAutoSelectInHomeNW = carrierConfig.getBoolean(
CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL);
- mButton4glte.setTitle(enhanced4glteModeTitleId);
+ mButton4glte.setTitle(enhanced4glteModeTitle);
mLteDataServicePref.setEnabled(hasActiveSubscriptions);
Preference ps;
ps = findPreference(BUTTON_CELL_BROADCAST_SETTINGS);
@@ -1303,8 +1300,7 @@
mButtonEnabledNetworks.setEntryValues(
R.array.enabled_networks_values);
}
- updateGsmUmtsOptions(this, getPreferenceScreen(), mSubId,
- mNetworkQueryService);
+ updateGsmUmtsOptions(this, getPreferenceScreen(), mSubId);
} else {
throw new IllegalStateException("Unexpected phone type: " + phoneType);
}
@@ -1868,7 +1864,7 @@
TelecomManager.from(getContext()).getSimCallManager();
if (simCallManager != null) {
- Intent intent = PhoneAccountSettingsFragment.buildPhoneAccountConfigureIntent(
+ Intent intent = MobileNetworkSettings.buildPhoneAccountConfigureIntent(
getContext(), simCallManager);
PackageManager pm = getContext().getPackageManager();
List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0);
@@ -2048,7 +2044,7 @@
return;
}
- updateGsmUmtsOptions(this, prefSet, mSubId, mNetworkQueryService);
+ updateGsmUmtsOptions(this, prefSet, mSubId);
PreferenceCategory networkOperatorCategory =
(PreferenceCategory) prefSet.findPreference(
@@ -2201,14 +2197,14 @@
}
private void updateGsmUmtsOptions(PreferenceFragment prefFragment,
- PreferenceScreen prefScreen, final int subId, INetworkQueryService queryService) {
+ PreferenceScreen prefScreen, final int subId) {
// We don't want to re-create GsmUmtsOptions if already exists. Otherwise, the
// preferences inside it will also be re-created which causes unexpected behavior.
// For example, the open dialog gets dismissed or detached after pause / resume.
if (mGsmUmtsOptions == null) {
- mGsmUmtsOptions = new GsmUmtsOptions(prefFragment, prefScreen, subId, queryService);
+ mGsmUmtsOptions = new GsmUmtsOptions(prefFragment, prefScreen, subId);
} else {
- mGsmUmtsOptions.update(subId, queryService);
+ mGsmUmtsOptions.update(subId);
}
}
diff --git a/src/com/android/phone/NetworkOperators.java b/src/com/android/phone/NetworkOperators.java
index 6d798b0..938ca34 100644
--- a/src/com/android/phone/NetworkOperators.java
+++ b/src/com/android/phone/NetworkOperators.java
@@ -94,12 +94,11 @@
}
/**
- * Update NetworkOperators instance if like subId or queryService are updated.
+ * Update NetworkOperators instance if like subId is updated.
*
* @param subId Corresponding subscription ID of this network.
- * @param queryService The service to do network queries.
*/
- protected void update(final int subId, INetworkQueryService queryService) {
+ protected void update(final int subId) {
mSubId = subId;
mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId);
@@ -118,7 +117,7 @@
}
} else {
if (mNetworkSelect != null) {
- mNetworkSelect.initialize(mSubId, queryService, this, mProgressDialog);
+ mNetworkSelect.initialize(mSubId, this, mProgressDialog);
}
}
getNetworkSelectionMode();
diff --git a/src/com/android/phone/NetworkScanHelper.java b/src/com/android/phone/NetworkScanHelper.java
new file mode 100644
index 0000000..a21f547
--- /dev/null
+++ b/src/com/android/phone/NetworkScanHelper.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2018 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.phone;
+
+import android.annotation.IntDef;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.CellInfo;
+import android.telephony.NetworkScan;
+import android.telephony.NetworkScanRequest;
+import android.telephony.RadioAccessSpecifier;
+import android.telephony.TelephonyManager;
+import android.telephony.TelephonyScanManager;
+import android.util.Log;
+
+import com.android.internal.telephony.CellNetworkScanResult;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
+
+/**
+ * A helper class that builds the common interface and performs the network scan for two different
+ * network scan APIs.
+ */
+public class NetworkScanHelper {
+ public static final String TAG = "NetworkScanHelper";
+ private static final boolean DBG = true;
+
+ /**
+ * Callbacks interface to inform the network scan results.
+ */
+ public interface NetworkScanCallback {
+ /**
+ * Called when the results is returned from {@link TelephonyManager}. This method will be
+ * called at least one time if there is no error occurred during the network scan.
+ *
+ * <p> This method can be called multiple times in one network scan, until
+ * {@link #onComplete()} or {@link #onError(int)} is called.
+ *
+ * @param results
+ */
+ void onResults(List<CellInfo> results);
+
+ /**
+ * Called when the current network scan process is finished. No more
+ * {@link #onResults(List)} will be called for the current network scan after this method is
+ * called.
+ */
+ void onComplete();
+
+ /**
+ * Called when an error occurred during the network scan process.
+ *
+ * <p> There is no more result returned from {@link TelephonyManager} if an error occurred.
+ *
+ * <p> {@link #onComplete()} will not be called if an error occurred.
+ *
+ * @see {@link android.telephony.NetworkScan.ScanErrorCode}
+ */
+ void onError(int errorCode);
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS, NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS})
+ public @interface NetworkQueryType {}
+
+ /**
+ * Performs the network scan using {@link TelephonyManager#getAvailableNetworks()}. The network
+ * scan results won't be returned to the caller until the network scan is completed.
+ *
+ * <p> This is typically used when the modem doesn't support the new network scan api
+ * {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
+ */
+ public static final int NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS = 1;
+
+ /**
+ * Performs the network scan using {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)} The network scan
+ * results will be returned to the caller periodically in a small time window until the network
+ * scan is completed. The complete results should be returned in the last called of
+ * {@link NetworkScanCallback#onResults(List)}.
+ *
+ * <p> This is recommended to be used if modem supports the new network scan api
+ * {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
+ */
+ public static final int NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS = 2;
+
+ /** The constants below are used in the async network scan. */
+ private static final boolean INCREMENTAL_RESULTS = true;
+ private static final int SEARCH_PERIODICITY_SEC = 5;
+ private static final int MAX_SEARCH_TIME_SEC = 300;
+ private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3;
+
+ private static final NetworkScanRequest NETWORK_SCAN_REQUEST =
+ new NetworkScanRequest(
+ NetworkScanRequest.SCAN_TYPE_ONE_SHOT,
+ new RadioAccessSpecifier[]{
+ // GSM
+ new RadioAccessSpecifier(
+ AccessNetworkType.GERAN,
+ null /* bands */,
+ null /* channels */),
+ // LTE
+ new RadioAccessSpecifier(
+ AccessNetworkType.EUTRAN,
+ null /* bands */,
+ null /* channels */),
+ // WCDMA
+ new RadioAccessSpecifier(
+ AccessNetworkType.UTRAN,
+ null /* bands */,
+ null /* channels */)
+ },
+ SEARCH_PERIODICITY_SEC,
+ MAX_SEARCH_TIME_SEC,
+ INCREMENTAL_RESULTS,
+ INCREMENTAL_RESULTS_PERIODICITY_SEC,
+ null /* List of PLMN ids (MCC-MNC) */);
+
+ private final NetworkScanCallback mNetworkScanCallback;
+ private final TelephonyManager mTelephonyManager;
+ private final TelephonyScanManager.NetworkScanCallback mInternalNetworkScanCallback;
+ private final Executor mExecutor;
+
+ private NetworkScan mNetworkScanRequester;
+
+ /** Callbacks for sync network scan */
+ private ListenableFuture<List<CellInfo>> mNetworkScanFuture;
+
+ public NetworkScanHelper(TelephonyManager tm, NetworkScanCallback callback, Executor executor) {
+ mTelephonyManager = tm;
+ mNetworkScanCallback = callback;
+ mInternalNetworkScanCallback = new NetworkScanCallbackImpl();
+ mExecutor = executor;
+ }
+
+ /**
+ * Performs a network scan for the given type {@code type}.
+ * {@link #NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS} is recommended if modem supports
+ * {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
+ *
+ * @param type used to tell which network scan API should be used.
+ */
+ public void startNetworkScan(@NetworkQueryType int type) {
+ if (type == NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS) {
+ mNetworkScanFuture = SettableFuture.create();
+ Futures.addCallback(mNetworkScanFuture, new FutureCallback<List<CellInfo>>() {
+ @Override
+ public void onSuccess(List<CellInfo> result) {
+ onResults(result);
+ onComplete();
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ int errCode = Integer.parseInt(t.getMessage());
+ onError(errCode);
+ }
+ });
+ mExecutor.execute(new NetworkScanSyncTask(
+ mTelephonyManager, (SettableFuture) mNetworkScanFuture));
+ } else if (type == NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS) {
+ if (DBG) Log.d(TAG, "start network scan async");
+ mNetworkScanRequester = mTelephonyManager.requestNetworkScan(
+ NETWORK_SCAN_REQUEST,
+ mExecutor,
+ mInternalNetworkScanCallback);
+ }
+ }
+
+ /**
+ * The network scan of type {@link #NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS} can't be stopped,
+ * however, the result of the current network scan won't be returned to the callback after
+ * calling this method.
+ */
+ public void stopNetworkQuery() {
+ if (mNetworkScanRequester != null) {
+ mNetworkScanRequester.stopScan();
+ mNetworkScanFuture = null;
+ }
+
+ if (mNetworkScanFuture != null) {
+ mNetworkScanFuture.cancel(true /* mayInterruptIfRunning */);
+ mNetworkScanFuture = null;
+ }
+ }
+
+ private void onResults(List<CellInfo> cellInfos) {
+ mNetworkScanCallback.onResults(cellInfos);
+ }
+
+ private void onComplete() {
+ mNetworkScanCallback.onComplete();
+ }
+
+ private void onError(int errCode) {
+ mNetworkScanCallback.onError(errCode);
+ }
+
+ /**
+ * Converts the status code of {@link CellNetworkScanResult} to one of the
+ * {@link android.telephony.NetworkScan.ScanErrorCode}.
+ * @param errCode status code from {@link CellNetworkScanResult}.
+ *
+ * @return one of the scan error code from {@link android.telephony.NetworkScan.ScanErrorCode}.
+ */
+ private static int convertToScanErrorCode(int errCode) {
+ switch (errCode) {
+ case CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE:
+ return NetworkScan.ERROR_RADIO_INTERFACE_ERROR;
+ case CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE:
+ default:
+ return NetworkScan.ERROR_MODEM_ERROR;
+ }
+ }
+
+ private final class NetworkScanCallbackImpl extends TelephonyScanManager.NetworkScanCallback {
+ public void onResults(List<CellInfo> results) {
+ if (DBG) Log.d(TAG, "async scan onResults() results = " + results);
+ NetworkScanHelper.this.onResults(results);
+ }
+
+ public void onComplete() {
+ if (DBG) Log.d(TAG, "async scan onComplete()");
+ NetworkScanHelper.this.onComplete();
+ }
+
+ public void onError(@NetworkScan.ScanErrorCode int errCode) {
+ if (DBG) Log.d(TAG, "async scan onError() errorCode = " + errCode);
+ NetworkScanHelper.this.onError(errCode);
+ }
+ }
+
+ private static final class NetworkScanSyncTask implements Runnable {
+ private final SettableFuture<List<CellInfo>> mCallback;
+ private final TelephonyManager mTelephonyManager;
+
+ NetworkScanSyncTask(
+ TelephonyManager telephonyManager, SettableFuture<List<CellInfo>> callback) {
+ mTelephonyManager = telephonyManager;
+ mCallback = callback;
+ }
+
+ @Override
+ public void run() {
+ if (DBG) Log.d(TAG, "sync scan start");
+ CellNetworkScanResult result = mTelephonyManager.getAvailableNetworks();
+ if (result.getStatus() == CellNetworkScanResult.STATUS_SUCCESS) {
+ List<CellInfo> cellInfos = result.getOperators()
+ .stream()
+ .map(operatorInfo
+ -> CellInfoUtil.convertOperatorInfoToCellInfo(operatorInfo))
+ .collect(Collectors.toList());
+ if (DBG) Log.d(TAG, "sync scan complete");
+ mCallback.set(cellInfos);
+ } else {
+ mCallback.setException(new Throwable(
+ Integer.toString(convertToScanErrorCode(result.getStatus()))));
+ }
+ }
+ }
+}
diff --git a/src/com/android/phone/NetworkSelectListPreference.java b/src/com/android/phone/NetworkSelectListPreference.java
index 5b841c9..9af1c77 100644
--- a/src/com/android/phone/NetworkSelectListPreference.java
+++ b/src/com/android/phone/NetworkSelectListPreference.java
@@ -24,7 +24,6 @@
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.RemoteException;
import android.preference.ListPreference;
import android.preference.Preference;
import android.telephony.CellInfo;
@@ -39,15 +38,19 @@
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
+import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.telephony.OperatorInfo;
+import com.android.phone.NetworkScanHelper.NetworkScanCallback;
import com.android.settingslib.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
/**
@@ -65,16 +68,20 @@
private static final int EVENT_MANUALLY_NETWORK_SELECTION_DONE = 1;
private static final int EVENT_NETWORK_SCAN_RESULTS = 2;
private static final int EVENT_NETWORK_SCAN_COMPLETED = 3;
+ private static final int EVENT_NETWORK_SCAN_ERROR = 4;
//dialog ids
private static final int DIALOG_NETWORK_SELECTION = 100;
private static final int DIALOG_NETWORK_LIST_LOAD = 200;
+ private final ExecutorService mNetworkScanExecutor = Executors.newFixedThreadPool(1);
+
private List<CellInfo> mCellInfoList;
private CellInfo mCellInfo;
private int mSubId;
private TelephonyManager mTelephonyManager;
+ private NetworkScanHelper mNetworkScanHelper;
private NetworkOperators mNetworkOperators;
private List<String> mForbiddenPlmns;
@@ -113,11 +120,7 @@
switch (msg.what) {
case EVENT_MANUALLY_NETWORK_SELECTION_DONE:
if (DBG) logd("hideProgressPanel");
- try {
- dismissProgressBar();
- } catch (IllegalArgumentException e) {
- }
- setEnabled(true);
+ dismissProgressDialog();
boolean isSuccessed = (boolean) msg.obj;
if (isSuccessed) {
@@ -138,72 +141,51 @@
results.removeIf(cellInfo -> cellInfo == null);
mCellInfoList = new ArrayList<>(results);
if (DBG) logd("CALLBACK_SCAN_RESULTS" + mCellInfoList.toString());
-
break;
case EVENT_NETWORK_SCAN_COMPLETED:
- try {
- if (mNetworkQueryService != null) {
- mNetworkQueryService.unregisterCallback(mCallback);
- }
- } catch (RemoteException e) {
- loge("onComplete: exception from unregisterCallback " + e);
- }
if (DBG) logd("scan complete, load the cellInfosList");
- // Modify UI to indicate users that the scan has completed.
+ dismissProgressDialog();
networksListLoaded();
+ break;
+ case EVENT_NETWORK_SCAN_ERROR:
+ dismissProgressDialog();
+ displayNetworkQueryFailed();
+ mNetworkOperators.getNetworkSelectionMode();
+ break;
}
return;
}
};
- INetworkQueryService mNetworkQueryService = null;
- /**
- * This implementation of INetworkQueryServiceCallback is used to receive
- * callback notifications from the network query service.
- */
- private final INetworkQueryServiceCallback mCallback = new INetworkQueryServiceCallback.Stub() {
-
- /** Returns the scan results to the user, this callback will be called only one time. */
+ private final NetworkScanHelper.NetworkScanCallback mCallback = new NetworkScanCallback() {
public void onResults(List<CellInfo> results) {
if (DBG) logd("get scan results: " + results.toString());
Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RESULTS, results);
msg.sendToTarget();
}
- /**
- * Informs the user that the scan has stopped.
- *
- * This callback will be called when the scan is finished or cancelled by the user.
- * The related NetworkScanRequest will be deleted after this callback.
- */
public void onComplete() {
if (DBG) logd("network scan completed.");
Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED);
msg.sendToTarget();
}
- /**
- * This callback will not be called, since the old Scan API won't send this callback.
- */
- public void onError(int error) {}
+ public void onError(int error) {
+ if (DBG) logd("network scan error.");
+ Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_ERROR);
+ msg.sendToTarget();
+ }
};
@Override
//implemented for DialogInterface.OnCancelListener
public void onCancel(DialogInterface dialog) {
if (DBG) logd("user manually close the dialog");
- // request that the service stop the query with this callback object.
- try {
- if (mNetworkQueryService != null) {
- mNetworkQueryService.stopNetworkQuery();
- mNetworkQueryService.unregisterCallback(mCallback);
- }
- // If cancelled, we query NetworkSelectMode and update states of AutoSelect button.
- mNetworkOperators.getNetworkSelectionMode();
- } catch (RemoteException e) {
- loge("onCancel: exception from stopNetworkQuery " + e);
- }
+ mNetworkScanHelper.stopNetworkQuery();
+
+ // If cancelled, we query NetworkSelectMode and update states of AutoSelect button.
+ mNetworkOperators.getNetworkSelectionMode();
}
@Override
@@ -215,23 +197,17 @@
}
}
- // This method is provided besides initialize() because bind to network query service
- // may be binded after initialize(). In that case this method needs to be called explicitly
- // to set mNetworkQueryService. Otherwise mNetworkQueryService will remain null.
- public void setNetworkQueryService(INetworkQueryService queryService) {
- mNetworkQueryService = queryService;
- }
-
// This initialize method needs to be called for this preference to work properly.
- protected void initialize(int subId, INetworkQueryService queryService,
- NetworkOperators networkOperators, ProgressDialog progressDialog) {
+ protected void initialize(int subId, NetworkOperators networkOperators,
+ ProgressDialog progressDialog) {
mSubId = subId;
- mNetworkQueryService = queryService;
mNetworkOperators = networkOperators;
// This preference should share the same progressDialog with networkOperators category.
mProgressDialog = progressDialog;
mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId);
+ mNetworkScanHelper = new NetworkScanHelper(
+ mTelephonyManager, mCallback, mNetworkScanExecutor);
setSummary(mTelephonyManager.getNetworkOperatorName());
@@ -245,79 +221,32 @@
}
private void destroy() {
- try {
- dismissProgressBar();
- } catch (IllegalArgumentException e) {
- loge("onDestroy: exception from dismissProgressBar " + e);
+ dismissProgressDialog();
+
+ if (mNetworkScanHelper != null) {
+ mNetworkScanHelper.stopNetworkQuery();
}
- try {
- if (mNetworkQueryService != null) {
- // used to un-register callback
- mNetworkQueryService.unregisterCallback(mCallback);
- }
- } catch (RemoteException e) {
- loge("onDestroy: exception from unregisterCallback " + e);
- }
+ mNetworkScanExecutor.shutdown();
}
private void displayEmptyNetworkList() {
- String status = getContext().getResources().getString(R.string.empty_networks_list);
-
- final PhoneGlobals app = PhoneGlobals.getInstance();
- app.notificationMgr.postTransientNotification(
- NotificationMgr.NETWORK_SELECTION_NOTIFICATION, status);
+ Toast.makeText(getContext(), R.string.empty_networks_list, Toast.LENGTH_LONG).show();
}
- private void displayNetworkSelectionInProgress() {
- showProgressDialog(DIALOG_NETWORK_SELECTION);
- }
-
- private void displayNetworkQueryFailed(int error) {
- String status = getContext().getResources().getString(R.string.network_query_error);
-
- try {
- dismissProgressBar();
- } catch (IllegalArgumentException e1) {
- // do nothing
- }
-
- final PhoneGlobals app = PhoneGlobals.getInstance();
- app.notificationMgr.postTransientNotification(
- NotificationMgr.NETWORK_SELECTION_NOTIFICATION, status);
+ private void displayNetworkQueryFailed() {
+ Toast.makeText(getContext(), R.string.network_query_error, Toast.LENGTH_LONG).show();
}
private void loadNetworksList() {
if (DBG) logd("load networks list...");
- try {
- if (mNetworkQueryService != null) {
- mNetworkQueryService.startNetworkQuery(
- mCallback, mSubId, false /* isIncrementalResult */);
- } else {
- displayNetworkQueryFailed(NetworkQueryService.QUERY_EXCEPTION);
- }
- } catch (RemoteException e) {
- loge("loadNetworksList: exception from startNetworkQuery " + e);
- displayNetworkQueryFailed(NetworkQueryService.QUERY_EXCEPTION);
- }
+ mNetworkScanHelper.startNetworkScan(
+ NetworkScanHelper.NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS);
}
private void networksListLoaded() {
if (DBG) logd("networks list loaded");
- // update the state of the preferences.
- if (DBG) logd("hideProgressPanel");
-
- // Always try to dismiss the dialog because activity may
- // be moved to background after dialog is shown.
- try {
- dismissProgressBar();
- } catch (IllegalArgumentException e) {
- // It's not a error in following scenario, we just ignore it.
- // "Load list" dialog will not show, if NetworkQueryService is
- // connected after this activity is moved to background.
- loge("Fail to dismiss network load list dialog " + e);
- }
mNetworkOperators.getNetworkSelectionMode();
if (mCellInfoList != null) {
// create a preference for each item in the list.
@@ -345,9 +274,13 @@
}
}
- private void dismissProgressBar() {
+ private void dismissProgressDialog() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
- mProgressDialog.dismiss();
+ try {
+ mProgressDialog.dismiss();
+ } catch (IllegalArgumentException ex) {
+ loge("Can't close the progress dialog " + ex);
+ }
}
}
@@ -356,7 +289,7 @@
mProgressDialog = new ProgressDialog(getContext());
} else {
// Dismiss progress bar if it's showing now.
- dismissProgressBar();
+ dismissProgressDialog();
}
switch (id) {
diff --git a/src/com/android/phone/NetworkSelectSetting.java b/src/com/android/phone/NetworkSelectSetting.java
index c8a29ce..66cd8a1 100644
--- a/src/com/android/phone/NetworkSelectSetting.java
+++ b/src/com/android/phone/NetworkSelectSetting.java
@@ -17,17 +17,12 @@
import android.app.ActionBar;
import android.app.Activity;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IBinder;
import android.os.Message;
-import android.os.RemoteException;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
@@ -47,6 +42,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.telephony.OperatorInfo;
+import com.android.phone.NetworkScanHelper.NetworkScanCallback;
import com.android.settingslib.utils.ThreadUtils;
import java.util.ArrayList;
@@ -54,6 +50,8 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
/**
* "Choose network" settings UI for the Phone app.
@@ -86,6 +84,8 @@
private TelephonyManager mTelephonyManager;
private List<String> mForbiddenPlmns;
private boolean mShow4GForLTE;
+ private NetworkScanHelper mNetworkScanHelper;
+ private final ExecutorService mNetworkScanExecutor = Executors.newFixedThreadPool(1);
private final Runnable mUpdateNetworkOperatorsRunnable = () -> {
updateNetworkOperatorsPreferenceCategory();
@@ -118,6 +118,8 @@
mStatusMessagePreference = new Preference(getContext());
mSelectedNetworkOperatorPreference = null;
mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId);
+ mNetworkScanHelper = new NetworkScanHelper(
+ mTelephonyManager, mCallback, mNetworkScanExecutor);
try {
Context con = getActivity().createPackageContext("com.android.systemui", 0);
int id = con.getResources().getIdentifier("config_show4GForLTE",
@@ -172,7 +174,7 @@
@Override
protected void onPostExecute(List<String> result) {
mForbiddenPlmns = result;
- bindNetworkQueryService();
+ loadNetworksList();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@@ -260,8 +262,6 @@
if (DBG) logd("onStop");
getView().removeCallbacks(mUpdateNetworkOperatorsRunnable);
stopNetworkQuery();
- // Unbind the NetworkQueryService
- unbindNetworkQueryService();
}
private final Handler mHandler = new Handler() {
@@ -320,52 +320,23 @@
private void loadNetworksList() {
if (DBG) logd("load networks list...");
setProgressBarVisible(true);
- try {
- if (mNetworkQueryService != null) {
- if (DBG) logd("start network query");
- mNetworkQueryService
- .startNetworkQuery(mCallback, mSubId, true /* is incremental result */);
- } else {
- if (DBG) logd("unable to start network query, mNetworkQueryService is null");
- addMessagePreference(R.string.network_query_error);
- }
- } catch (RemoteException e) {
- loge("loadNetworksList: exception from startNetworkQuery " + e);
- addMessagePreference(R.string.network_query_error);
- }
+ mNetworkScanHelper.startNetworkScan(
+ NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS);
}
- /**
- * This implementation of INetworkQueryServiceCallback is used to receive
- * callback notifications from the network query service.
- */
- private final INetworkQueryServiceCallback mCallback = new INetworkQueryServiceCallback.Stub() {
-
- /** Returns the scan results to the user, this callback will be called at lease one time. */
+ private final NetworkScanHelper.NetworkScanCallback mCallback = new NetworkScanCallback() {
public void onResults(List<CellInfo> results) {
if (DBG) logd("get scan results.");
Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RESULTS, results);
msg.sendToTarget();
}
- /**
- * Informs the user that the scan has stopped.
- *
- * This callback will be called when the scan is finished or cancelled by the user.
- * The related NetworkScanRequest will be deleted after this callback.
- */
public void onComplete() {
if (DBG) logd("network scan completed.");
Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED);
msg.sendToTarget();
}
- /**
- * Informs the user that there is some error about the scan.
- *
- * This callback will be called whenever there is any error about the scan, and the scan
- * will be terminated. onComplete() will NOT be called.
- */
public void onError(int error) {
if (DBG) logd("get onError callback with error code: " + error);
Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_ERROR, error, 0 /* arg2 */);
@@ -373,9 +344,6 @@
}
};
- /**
- * Updates network operators from {@link INetworkQueryServiceCallback#onResults()}.
- */
private void updateNetworkOperators() {
if (DBG) logd("updateNetworkOperators");
if (getActivity() != null) {
@@ -580,66 +548,18 @@
return new ArrayList<>(map.values());
}
- /**
- * Service connection code for the NetworkQueryService.
- * Handles the work of binding to a local object so that we can make
- * the appropriate service calls.
- */
-
- /** Local service interface */
- private INetworkQueryService mNetworkQueryService = null;
- /** Flag indicating whether we have called bind on the service. */
- boolean mShouldUnbind;
-
- /** Service connection */
- private final ServiceConnection mNetworkQueryServiceConnection = new ServiceConnection() {
-
- /** Handle the task of binding the local object to the service */
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) logd("connection created, binding local service.");
- mNetworkQueryService = ((NetworkQueryService.LocalBinder) service).getService();
- // Load the network list only when the service is well connected.
- loadNetworksList();
- }
-
- /** Handle the task of cleaning up the local binding */
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) logd("connection disconnected, cleaning local binding.");
- mNetworkQueryService = null;
- }
- };
-
- private void bindNetworkQueryService() {
- if (DBG) logd("bindNetworkQueryService");
- getContext().bindService(new Intent(getContext(), NetworkQueryService.class).setAction(
- NetworkQueryService.ACTION_LOCAL_BINDER),
- mNetworkQueryServiceConnection, Context.BIND_AUTO_CREATE);
- mShouldUnbind = true;
- }
-
- private void unbindNetworkQueryService() {
- if (DBG) logd("unbindNetworkQueryService");
- if (mShouldUnbind) {
- if (DBG) logd("mShouldUnbind is true");
- // unbind the service.
- getContext().unbindService(mNetworkQueryServiceConnection);
- mShouldUnbind = false;
- }
- }
-
private void stopNetworkQuery() {
- // Stop the network query process
- try {
- if (mNetworkQueryService != null) {
- if (DBG) logd("Stop network query");
- mNetworkQueryService.stopNetworkQuery();
- mNetworkQueryService.unregisterCallback(mCallback);
- }
- } catch (RemoteException e) {
- loge("Exception from stopNetworkQuery " + e);
+ if (mNetworkScanHelper != null) {
+ mNetworkScanHelper.stopNetworkQuery();
}
}
+ @Override
+ public void onDestroy() {
+ mNetworkScanExecutor.shutdown();
+ super.onDestroy();
+ }
+
private void logd(String msg) {
Log.d(TAG, msg);
}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index ecb4861..cef0e53 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -990,7 +990,9 @@
case EVENT_GET_ALL_CELL_INFO_DONE:
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
- request.result = (ar.exception == null) ? ar.result : new ArrayList<CellInfo>();
+ // If a timeout occurs, the response will be null
+ request.result = (ar.exception == null && ar.result != null)
+ ? ar.result : new ArrayList<CellInfo>();
synchronized (request) {
request.notifyAll();
}