Messaging: Remove GServices
We don't have an actual implementation returning anything but the defaults, so apply the defaults directly anywhere we need them Change-Id: Ic651b4b13977799f2f4d2c702c430798fbff77f8
This commit is contained in:
@@ -264,14 +264,6 @@
|
||||
android:theme="@style/BugleTheme"
|
||||
android:parentActivityName="com.android.messaging.ui.conversation.ConversationActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.debug.DebugMmsConfigActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:screenOrientation="user"
|
||||
android:theme="@style/BugleTheme.DialogActivity"
|
||||
android:exported="false">
|
||||
</activity>
|
||||
|
||||
<provider android:name=".datamodel.MessagingContentProvider" android:label="@string/app_name"
|
||||
android:authorities="com.android.messaging.datamodel.MessagingContentProvider"
|
||||
android:exported="false" >
|
||||
@@ -371,18 +363,6 @@
|
||||
android:excludeFromRecents="true">
|
||||
</activity>
|
||||
|
||||
<activity android:name=".ui.appsettings.ApnSettingsActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:screenOrientation="user"
|
||||
android:theme="@style/BugleTheme"
|
||||
android:parentActivityName="com.android.messaging.ui.appsettings.SettingsActivity" />
|
||||
|
||||
<activity android:name=".ui.appsettings.ApnEditorActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:screenOrientation="user"
|
||||
android:theme="@style/BugleTheme"
|
||||
android:parentActivityName="com.android.messaging.ui.appsettings.ApnSettingsActivity"/>
|
||||
|
||||
<receiver android:name=".receiver.BootAndPackageReplacedReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 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.
|
||||
-->
|
||||
|
||||
<!--
|
||||
This is the layout file for an ApnPreference in the ApnSettingsActivity. The preference
|
||||
is a list item.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:gravity="center_vertical"
|
||||
style="@style/ApnPreferenceLayoutStyle">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/text_layout"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:focusable="true"
|
||||
android:background="?android:attr/selectableItemBackground">
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="true"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/title"
|
||||
android:layout_alignStart="@android:id/title"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:maxLines="2" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/apn_radiobutton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dip"
|
||||
android:layout_marginEnd="8dip"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:clickable="true" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 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.
|
||||
-->
|
||||
<fragment
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
class="com.android.messaging.ui.debug.DebugMmsConfigFragment"
|
||||
android:id="@+id/debug_mmsconfig_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<com.android.messaging.ui.debug.DebugMmsConfigItemView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:background="@android:color/background_light"
|
||||
android:gravity="center_vertical"
|
||||
android:clickable="true"
|
||||
style="@style/DebugMmsConfigItemStyle" >
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="match_parent"
|
||||
android:singleLine="true"
|
||||
android:maxLines="1"
|
||||
android:gravity="center_vertical"/>
|
||||
<Switch
|
||||
android:id="@+id/switch_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone" />
|
||||
<TextView
|
||||
android:id="@+id/text_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:singleLine="true"
|
||||
android:gravity="center_vertical"
|
||||
android:visibility="gone"/>
|
||||
</com.android.messaging.ui.debug.DebugMmsConfigItemView>
|
||||
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 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"
|
||||
android:padding="6dp"
|
||||
android:background="@color/conversation_background"
|
||||
>
|
||||
|
||||
<ListView android:id="@+id/dump_file_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:drawSelectorOnTop="false"
|
||||
android:longClickable="false"/>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -1,53 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 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">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="16dp">
|
||||
<TextView
|
||||
android:id="@+id/sim_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/debug_sub_id_spinner_text" />
|
||||
<Spinner
|
||||
android:id="@+id/sim_selector"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#555555" />
|
||||
|
||||
<ListView
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:divider="@null"
|
||||
android:dividerHeight="0px" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 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.
|
||||
-->
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" >
|
||||
<item
|
||||
android:id="@+id/action_debug_options"
|
||||
android:orderInCategory="9900"
|
||||
android:title="@string/action_debug_options"
|
||||
android:showAsAction="never"/>
|
||||
|
||||
</menu>
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 The Android Open Source Project
|
||||
Copyright (C) 2024 The LineageOS Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -42,10 +43,4 @@
|
||||
android:title="@string/action_settings"
|
||||
appcompat:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_debug_options"
|
||||
android:orderInCategory="9900"
|
||||
android:title="@string/action_debug_options"
|
||||
appcompat:showAsAction="never"/>
|
||||
|
||||
</menu>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 The Android Open Source Project
|
||||
Copyright (C) 2024 The LineageOS Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -57,5 +58,4 @@
|
||||
<enum name="subcompact" value="2" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
<attr name="apnPreferenceStyle" format="reference" />
|
||||
</resources>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 The Android Open Source Project
|
||||
Copyright (C) 2024 The LineageOS Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -45,21 +46,12 @@
|
||||
<string name="wireless_alerts_key" translatable="false">buglesub_wireless_alerts_key</string>
|
||||
<string name="apn_list_pref_key" translatable="false">buglesub_apn_list</string>
|
||||
|
||||
<!-- Debug preferences -->
|
||||
<string name="debug_pref_key" translatable="false">debug_category</string>
|
||||
<string name="dump_sms_pref_key" translatable="false">dump_sms</string>
|
||||
<bool name="dump_sms_pref_default" translatable="false">false</bool>
|
||||
<string name="dump_mms_pref_key" translatable="false">dump_mms</string>
|
||||
<bool name="dump_mms_pref_default" translatable="false">false</bool>
|
||||
|
||||
|
||||
<!-- SMS/MMS settings keys -->
|
||||
<!--
|
||||
TODO: Several of these are currently unused but are expected to be needed to
|
||||
implement SMS/MMS delivery and basic settings. Once we have the core functionality in place
|
||||
we should do a pass to remove any unused values here.
|
||||
-->
|
||||
<string name="sms_apns_key" translatable="false">sms_apns_key</string>
|
||||
<string name="use_local_apn_pref_key" translatable="false">use_local_apn_pref_key</string>
|
||||
<bool name="use_local_apn_pref_default" translatable="false">false</bool>
|
||||
|
||||
|
||||
@@ -688,50 +688,6 @@
|
||||
<!-- Label for new message button in share intent dialog -->
|
||||
<string name="share_cancel">Cancel</string>
|
||||
|
||||
<!-- Screen title after user selects APNs setting option -->
|
||||
<string name="apn_edit">Edit access point</string>
|
||||
<!-- Edit access point label summary text when no value has been set -->
|
||||
<string name="apn_not_set">Not set</string>
|
||||
<!-- Edit access point labels: A label the user can give to the APN to allow him to differentiate it from the others -->
|
||||
<string name="apn_name">Name</string>
|
||||
<!-- Edit access point labels: -->
|
||||
<string name="apn_mmsc">MMSC</string>
|
||||
<!-- Edit access point labels: The proxy to use for MMS (multimedia messages)-->
|
||||
<string name="apn_mms_proxy">MMS proxy</string>
|
||||
<!-- Edit access point labels: The port on the proxy used for MMS-->
|
||||
<string name="apn_mms_port">MMS port</string>
|
||||
<!-- Edit access point labels: -->
|
||||
<string name="apn_mcc">MCC</string>
|
||||
<!-- Edit access point labels: -->
|
||||
<string name="apn_mnc">MNC</string>
|
||||
<!-- Edit access point screen menu option to delete this APN -->
|
||||
<string name="menu_delete_apn">Delete APN</string>
|
||||
<!-- APNs screen menu option to create a brand spanking new APN -->
|
||||
<string name="menu_new_apn">New APN</string>
|
||||
<!-- Edit access point screen menu option to save the user's changes for this APN to the persistent storage -->
|
||||
<string name="menu_save_apn">Save</string>
|
||||
<!-- Edit access point screen menu option to discard the user's changes for this APN -->
|
||||
<string name="menu_discard_apn_change">Discard</string>
|
||||
<!-- APN error dialog messages: -->
|
||||
<string name="error_apn_name_empty">The Name field can\'t be empty.</string>
|
||||
<!-- APN error dialog messages: -->
|
||||
<string name="error_mcc_not3">MCC field must be 3 digits.</string>
|
||||
<!-- APN error dialog messages: -->
|
||||
<string name="error_mnc_not23">MNC field must be 2 or 3 digits.</string>
|
||||
<!-- The message of dialog indicated restoring default APN settings in progress -->
|
||||
<string name="restore_default_apn">Restoring default APN settings.</string>
|
||||
<!-- APNs screen menu option to reset default APN settings -->
|
||||
<string name="menu_restore_default_apn">Reset to default</string>
|
||||
<!-- APNs screen toast message to inform reset default APN settings is completed -->
|
||||
<string name="restore_default_apn_completed">Reset default APN settings completed.</string>
|
||||
<!-- Name to assign to a Network Access Point that was saved without a name -->
|
||||
<string name="untitled_apn">Untitled</string>
|
||||
<!-- Title for Access Point Names settings -->
|
||||
<string name="sms_apns_title">Access Point Names</string>
|
||||
<!-- Title for Access Point Names settings activity -->
|
||||
<string name="apn_settings">APNs</string>
|
||||
<!-- Error message for users that aren't allowed to modify Access Point Names settings [CHAR LIMIT=none] -->
|
||||
<string name="apn_settings_not_available">Access Point Name settings are not available for this user</string>
|
||||
<!-- Alert dialog title to copy information displayed in dialog to system clipboard. -->
|
||||
<string name="copy_to_clipboard_dialog_title">Copy to clipboard?</string>
|
||||
<!-- Alert dialog accept to copy information displayed in dialog to system clipboard. -->
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
<item name="colorAccent">@color/lineage_accent</item>
|
||||
<item name="android:textColorHighlight">@color/text_highlight_color</item>
|
||||
<item name="actionBarStyle">@style/BugleActionBar</item>
|
||||
<item name="apnPreferenceStyle">@style/ApnPreference</item>
|
||||
<item name="alertDialogTheme">@style/AlertDialogTheme</item>
|
||||
</style>
|
||||
|
||||
@@ -466,15 +465,6 @@
|
||||
<item name="colorAccent">@color/search_view_text_cursor</item>
|
||||
</style>
|
||||
|
||||
<style name="ApnPreference">
|
||||
<item name="android:layout">@layout/apn_preference_layout</item>
|
||||
</style>
|
||||
|
||||
<style name="ApnPreferenceLayoutStyle">
|
||||
<item name="android:paddingStart">?android:attr/listPreferredItemPaddingStart</item>
|
||||
<item name="android:paddingEnd">?android:attr/listPreferredItemPaddingEnd</item>
|
||||
</style>
|
||||
|
||||
<style name="SettingsListItem">
|
||||
<item name="android:textSize">@dimen/settings_list_text_size</item>
|
||||
<item name="android:textColor">@color/settings_list_text_primary</item>
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
|
||||
android:title="@string/apn_edit">
|
||||
<EditTextPreference
|
||||
android:title="@string/apn_name"
|
||||
android:dialogTitle="@string/apn_name"
|
||||
android:key="apn_name"
|
||||
android:singleLine="true"
|
||||
android:inputType="text"
|
||||
/>
|
||||
<EditTextPreference
|
||||
android:title="@string/apn_mmsc"
|
||||
android:dialogTitle="@string/apn_mmsc"
|
||||
android:key="apn_mmsc"
|
||||
android:singleLine="true"
|
||||
android:inputType="textUri"
|
||||
/>
|
||||
<EditTextPreference
|
||||
android:title="@string/apn_mms_proxy"
|
||||
android:dialogTitle="@string/apn_mms_proxy"
|
||||
android:key="apn_mms_proxy"
|
||||
android:singleLine="true"
|
||||
android:inputType="textUri"
|
||||
/>
|
||||
<EditTextPreference
|
||||
android:title="@string/apn_mms_port"
|
||||
android:dialogTitle="@string/apn_mms_port"
|
||||
android:key="apn_mms_port"
|
||||
android:singleLine="true"
|
||||
android:inputType="number"
|
||||
/>
|
||||
<EditTextPreference
|
||||
android:title="@string/apn_mcc"
|
||||
android:dialogTitle="@string/apn_mcc"
|
||||
android:key="apn_mcc"
|
||||
android:singleLine="true"
|
||||
android:inputType="number"
|
||||
/>
|
||||
<EditTextPreference
|
||||
android:title="@string/apn_mnc"
|
||||
android:dialogTitle="@string/apn_mnc"
|
||||
android:key="apn_mnc"
|
||||
android:singleLine="true"
|
||||
android:inputType="number"
|
||||
/>
|
||||
</PreferenceScreen>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
|
||||
android:title="@string/apn_settings" android:key="@string/apn_list_pref_key">
|
||||
</PreferenceScreen>
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 The Android Open Source Project
|
||||
Copyright (C) 2024 The LineageOS Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -57,23 +58,4 @@
|
||||
<PreferenceScreen
|
||||
android:key="@string/advanced_pref_key"
|
||||
android:title="@string/advanced_settings" />
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/debug_pref_key"
|
||||
android:title="@string/debug_category_pref_title">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="@string/dump_sms_pref_key"
|
||||
android:title="@string/dump_sms_pref_title"
|
||||
android:summary="@string/dump_sms_pref_summary"
|
||||
android:defaultValue="@bool/dump_sms_pref_default" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="@string/dump_mms_pref_key"
|
||||
android:title="@string/dump_mms_pref_title"
|
||||
android:summary="@string/dump_mms_pref_summary"
|
||||
android:defaultValue="@bool/dump_mms_pref_default" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -55,9 +55,5 @@
|
||||
android:summary="@string/delivery_reports_pref_summary"
|
||||
android:defaultValue="@bool/delivery_reports_pref_default" />
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="@string/sms_apns_key"
|
||||
android:title="@string/sms_apns_title" />
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -33,21 +33,9 @@ public class MmsManager {
|
||||
*/
|
||||
public static final int DEFAULT_SUB_ID = -1;
|
||||
|
||||
// Whether to force legacy MMS sending
|
||||
private static volatile boolean sForceLegacyMms = false;
|
||||
|
||||
// Cached computed overrides for carrier configuration values
|
||||
private static final SparseArray<Bundle> sConfigOverridesMap = new SparseArray<>();
|
||||
|
||||
/**
|
||||
* Set the flag about whether to force to use legacy system APIs instead of system MMS API
|
||||
*
|
||||
* @param forceLegacyMms value to set
|
||||
*/
|
||||
public static void setForceLegacyMms(boolean forceLegacyMms) {
|
||||
sForceLegacyMms = forceLegacyMms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the size of thread pool for request execution.
|
||||
*
|
||||
@@ -136,14 +124,10 @@ public class MmsManager {
|
||||
*/
|
||||
public static void sendMultimediaMessage(int subId, Context context, Uri contentUri,
|
||||
String locationUrl, PendingIntent sentIntent) {
|
||||
if (shouldUseLegacyMms()) {
|
||||
MmsService.startRequest(context, new SendRequest(locationUrl, contentUri, sentIntent));
|
||||
} else {
|
||||
subId = Utils.getEffectiveSubscriptionId(subId);
|
||||
final SmsManager smsManager = Utils.getSmsManager(subId);
|
||||
smsManager.sendMultimediaMessage(context, contentUri, locationUrl,
|
||||
getConfigOverrides(subId), sentIntent);
|
||||
}
|
||||
subId = Utils.getEffectiveSubscriptionId(subId);
|
||||
final SmsManager smsManager = Utils.getSmsManager(subId);
|
||||
smsManager.sendMultimediaMessage(context, contentUri, locationUrl,
|
||||
getConfigOverrides(subId), sentIntent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,24 +142,10 @@ public class MmsManager {
|
||||
*/
|
||||
public static void downloadMultimediaMessage(int subId, Context context, String locationUrl,
|
||||
Uri contentUri, PendingIntent downloadedIntent) {
|
||||
if (shouldUseLegacyMms()) {
|
||||
MmsService.startRequest(context,
|
||||
new DownloadRequest(locationUrl, contentUri, downloadedIntent));
|
||||
} else {
|
||||
subId = Utils.getEffectiveSubscriptionId(subId);
|
||||
final SmsManager smsManager = Utils.getSmsManager(subId);
|
||||
smsManager.downloadMultimediaMessage(context, locationUrl, contentUri,
|
||||
getConfigOverrides(subId), downloadedIntent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if we should use legacy APIs for MMS.
|
||||
*
|
||||
* @return true if forced to use legacy APIs or platform doesn't supports MMS APIs.
|
||||
*/
|
||||
public static boolean shouldUseLegacyMms() {
|
||||
return sForceLegacyMms;
|
||||
subId = Utils.getEffectiveSubscriptionId(subId);
|
||||
final SmsManager smsManager = Utils.getSmsManager(subId);
|
||||
smsManager.downloadMultimediaMessage(context, locationUrl, contentUri,
|
||||
getConfigOverrides(subId), downloadedIntent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,9 +38,6 @@ import com.android.messaging.sms.BugleApnSettingsLoader;
|
||||
import com.android.messaging.sms.BugleUserAgentInfoLoader;
|
||||
import com.android.messaging.sms.MmsConfig;
|
||||
import com.android.messaging.ui.ConversationDrawables;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.BuglePrefs;
|
||||
import com.android.messaging.util.BuglePrefsKeys;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
@@ -83,8 +80,6 @@ public class BugleApplication extends Application implements UncaughtExceptionHa
|
||||
public void initializeSync(final Factory factory) {
|
||||
Trace.beginSection("app.initializeSync");
|
||||
final Context context = factory.getApplicationContext();
|
||||
final BugleGservices bugleGservices = factory.getBugleGservices();
|
||||
final BuglePrefs buglePrefs = factory.getApplicationPrefs();
|
||||
final DataModel dataModel = factory.getDataModel();
|
||||
final CarrierConfigValuesLoader carrierConfigValuesLoader =
|
||||
factory.getCarrierConfigValuesLoader();
|
||||
@@ -94,7 +89,7 @@ public class BugleApplication extends Application implements UncaughtExceptionHa
|
||||
BugleApplication.updateAppConfig(context);
|
||||
|
||||
// Initialize MMS lib
|
||||
initMmsLib(context, bugleGservices, carrierConfigValuesLoader);
|
||||
initMmsLib(context, carrierConfigValuesLoader);
|
||||
// Initialize APN database
|
||||
ApnDatabase.initializeAppContext(context);
|
||||
// Fixup messages in flight if we crashed and send any pending
|
||||
@@ -116,21 +111,12 @@ public class BugleApplication extends Application implements UncaughtExceptionHa
|
||||
Context.RECEIVER_EXPORTED/*UNAUDITED*/);
|
||||
}
|
||||
|
||||
private static void initMmsLib(final Context context, final BugleGservices bugleGservices,
|
||||
private static void initMmsLib(final Context context,
|
||||
final CarrierConfigValuesLoader carrierConfigValuesLoader) {
|
||||
MmsManager.setApnSettingsLoader(new BugleApnSettingsLoader(context));
|
||||
MmsManager.setCarrierConfigValuesLoader(carrierConfigValuesLoader);
|
||||
MmsManager.setUserAgentInfoLoader(new BugleUserAgentInfoLoader(context));
|
||||
MmsManager.setUseWakeLock(true);
|
||||
// If Gservices is configured not to use mms api, force MmsManager to always use
|
||||
// legacy mms sending logic
|
||||
MmsManager.setForceLegacyMms(!bugleGservices.getBoolean(
|
||||
BugleGservicesKeys.USE_MMS_API_IF_PRESENT,
|
||||
BugleGservicesKeys.USE_MMS_API_IF_PRESENT_DEFAULT));
|
||||
bugleGservices.registerForChanges(() -> MmsManager.setForceLegacyMms(
|
||||
!bugleGservices.getBoolean(
|
||||
BugleGservicesKeys.USE_MMS_API_IF_PRESENT,
|
||||
BugleGservicesKeys.USE_MMS_API_IF_PRESENT_DEFAULT)));
|
||||
}
|
||||
|
||||
public static void updateAppConfig(final Context context) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +27,6 @@ import com.android.messaging.datamodel.media.MediaResourceManager;
|
||||
import com.android.messaging.sms.BugleCarrierConfigValuesLoader;
|
||||
import com.android.messaging.ui.UIIntents;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BuglePrefs;
|
||||
import com.android.messaging.util.MediaUtil;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
@@ -56,7 +56,6 @@ public abstract class Factory {
|
||||
|
||||
public abstract Context getApplicationContext();
|
||||
public abstract DataModel getDataModel();
|
||||
public abstract BugleGservices getBugleGservices();
|
||||
public abstract BuglePrefs getApplicationPrefs();
|
||||
public abstract BuglePrefs getSubscriptionPrefs(int subId);
|
||||
public abstract BuglePrefs getWidgetPrefs();
|
||||
|
||||
@@ -35,8 +35,6 @@ import com.android.messaging.ui.UIIntents;
|
||||
import com.android.messaging.ui.UIIntentsImpl;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.BugleApplicationPrefs;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesImpl;
|
||||
import com.android.messaging.util.BuglePrefs;
|
||||
import com.android.messaging.util.BugleSubscriptionPrefs;
|
||||
import com.android.messaging.util.BugleWidgetPrefs;
|
||||
@@ -51,7 +49,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
class FactoryImpl extends Factory {
|
||||
private BugleApplication mApplication;
|
||||
private DataModel mDataModel;
|
||||
private BugleGservices mBugleGservices;
|
||||
private BugleApplicationPrefs mBugleApplicationPrefs;
|
||||
private BugleWidgetPrefs mBugleWidgetPrefs;
|
||||
private Context mApplicationContext;
|
||||
@@ -89,7 +86,6 @@ class FactoryImpl extends Factory {
|
||||
factory.mMemoryCacheManager = new MemoryCacheManager();
|
||||
factory.mMediaCacheManager = new BugleMediaCacheManager();
|
||||
factory.mMediaResourceManager = new MediaResourceManager();
|
||||
factory.mBugleGservices = new BugleGservicesImpl(applicationContext);
|
||||
factory.mBugleApplicationPrefs = new BugleApplicationPrefs(applicationContext);
|
||||
factory.mDataModel = new DataModelImpl(applicationContext);
|
||||
factory.mBugleWidgetPrefs = new BugleWidgetPrefs(applicationContext);
|
||||
@@ -99,9 +95,6 @@ class FactoryImpl extends Factory {
|
||||
factory.mSubscriptionPrefs = new SparseArray<BugleSubscriptionPrefs>();
|
||||
factory.mCarrierConfigValuesLoader = new BugleCarrierConfigValuesLoader(applicationContext);
|
||||
|
||||
Assert.initializeGservices(factory.mBugleGservices);
|
||||
LogUtil.initializeGservices(factory.mBugleGservices);
|
||||
|
||||
if (OsUtil.hasRequiredPermissions()) {
|
||||
factory.onRequiredPermissionsAcquired();
|
||||
}
|
||||
@@ -135,11 +128,6 @@ class FactoryImpl extends Factory {
|
||||
return mDataModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BugleGservices getBugleGservices() {
|
||||
return mBugleGservices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuglePrefs getApplicationPrefs() {
|
||||
return mBugleApplicationPrefs;
|
||||
|
||||
@@ -68,7 +68,6 @@ import com.android.messaging.sms.MmsUtils;
|
||||
import com.android.messaging.ui.UIIntents;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.AvatarUriUtil;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.BuglePrefs;
|
||||
import com.android.messaging.util.BuglePrefsKeys;
|
||||
@@ -605,10 +604,9 @@ public class BugleNotifications {
|
||||
// Find out the last time we dinged for this conversation
|
||||
Long lastTime = sLastMessageDingTime.get(conversationId);
|
||||
if (sTimeBetweenDingsMs == 0) {
|
||||
sTimeBetweenDingsMs = BugleGservices.get().getInt(
|
||||
BugleGservicesKeys.NOTIFICATION_TIME_BETWEEN_RINGS_SECONDS,
|
||||
BugleGservicesKeys.NOTIFICATION_TIME_BETWEEN_RINGS_SECONDS_DEFAULT) *
|
||||
1000;
|
||||
sTimeBetweenDingsMs =
|
||||
BugleGservicesKeys.NOTIFICATION_TIME_BETWEEN_RINGS_SECONDS_DEFAULT *
|
||||
1000;
|
||||
}
|
||||
if (lastTime == null
|
||||
|| SystemClock.elapsedRealtime() - lastTime > sTimeBetweenDingsMs) {
|
||||
|
||||
@@ -27,17 +27,13 @@ import android.database.sqlite.SQLiteQueryBuilder;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.messaging.Factory;
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
import com.android.messaging.util.UiUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class DatabaseWrapper {
|
||||
private static final String TAG = LogUtil.BUGLE_DATABASE_TAG;
|
||||
@@ -45,12 +41,6 @@ public class DatabaseWrapper {
|
||||
private final SQLiteDatabase mDatabase;
|
||||
private final Context mContext;
|
||||
private final boolean mLog;
|
||||
/**
|
||||
* Set mExplainQueryPlanRegexp (via {@link BugleGservicesKeys#EXPLAIN_QUERY_PLAN_REGEXP}
|
||||
* to regex matching queries to see query plans. For example, ".*" to show all query plans.
|
||||
*/
|
||||
// See
|
||||
private final String mExplainQueryPlanRegexp;
|
||||
private static final int sTimingThreshold = 50; // in milliseconds
|
||||
|
||||
public static final int INDEX_INSERT_MESSAGE_PART = 0;
|
||||
@@ -77,8 +67,6 @@ public class DatabaseWrapper {
|
||||
|
||||
DatabaseWrapper(final Context context, final SQLiteDatabase db) {
|
||||
mLog = LogUtil.isLoggable(LogUtil.BUGLE_DATABASE_PERF_TAG, LogUtil.VERBOSE);
|
||||
mExplainQueryPlanRegexp = Factory.get().getBugleGservices().getString(
|
||||
BugleGservicesKeys.EXPLAIN_QUERY_PLAN_REGEXP, null);
|
||||
mDatabase = db;
|
||||
mContext = context;
|
||||
mCompiledStatements = new SparseArray<SQLiteStatement>();
|
||||
@@ -96,10 +84,6 @@ public class DatabaseWrapper {
|
||||
return compiled;
|
||||
}
|
||||
|
||||
private void maybePlayDebugNoise() {
|
||||
DebugUtils.maybePlayDebugNoise(mContext, DebugUtils.DEBUG_SOUND_DB_OP);
|
||||
}
|
||||
|
||||
private static void printTiming(final long t1, final String msg) {
|
||||
final int transactionDepth = sTransactionDepth.get().size();
|
||||
final long t2 = System.currentTimeMillis();
|
||||
@@ -190,64 +174,10 @@ public class DatabaseWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
private void explainQueryPlan(final SQLiteQueryBuilder qb, final SQLiteDatabase db,
|
||||
final String[] projection, final String selection,
|
||||
@SuppressWarnings("unused")
|
||||
final String[] queryArgs,
|
||||
final String groupBy,
|
||||
@SuppressWarnings("unused")
|
||||
final String having,
|
||||
final String sortOrder, final String limit) {
|
||||
final String queryString = qb.buildQuery(
|
||||
projection,
|
||||
selection,
|
||||
groupBy,
|
||||
null/*having*/,
|
||||
sortOrder,
|
||||
limit);
|
||||
explainQueryPlan(db, queryString, queryArgs);
|
||||
}
|
||||
|
||||
private void explainQueryPlan(final SQLiteDatabase db, final String sql,
|
||||
final String[] queryArgs) {
|
||||
if (!Pattern.matches(mExplainQueryPlanRegexp, sql)) {
|
||||
return;
|
||||
}
|
||||
final Cursor planCursor = db.rawQuery("explain query plan " + sql, queryArgs);
|
||||
try {
|
||||
if (planCursor != null && planCursor.moveToFirst()) {
|
||||
final int detailColumn = planCursor.getColumnIndex("detail");
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
do {
|
||||
sb.append(planCursor.getString(detailColumn));
|
||||
sb.append("\n");
|
||||
} while (planCursor.moveToNext());
|
||||
if (sb.length() > 0) {
|
||||
sb.setLength(sb.length() - 1);
|
||||
}
|
||||
LogUtil.v(TAG, "for query " + sql + "\nplan is: "
|
||||
+ sb);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
LogUtil.w(TAG, "Query plan failed ", e);
|
||||
} finally {
|
||||
if (planCursor != null) {
|
||||
planCursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Cursor query(final String searchTable, final String[] projection,
|
||||
final String selection, final String[] selectionArgs, final String groupBy,
|
||||
final String having, final String orderBy, final String limit) {
|
||||
if (mExplainQueryPlanRegexp != null) {
|
||||
final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
|
||||
qb.setTables(searchTable);
|
||||
explainQueryPlan(qb, mDatabase, projection, selection, selectionArgs,
|
||||
groupBy, having, orderBy, limit);
|
||||
}
|
||||
|
||||
maybePlayDebugNoise();
|
||||
long t1 = 0;
|
||||
if (mLog) {
|
||||
t1 = System.currentTimeMillis();
|
||||
@@ -274,11 +204,6 @@ public class DatabaseWrapper {
|
||||
public Cursor query(final SQLiteQueryBuilder qb,
|
||||
final String[] projection, final String selection, final String[] queryArgs,
|
||||
final String groupBy, final String having, final String sortOrder, final String limit) {
|
||||
if (mExplainQueryPlanRegexp != null) {
|
||||
explainQueryPlan(qb, mDatabase, projection, selection, queryArgs,
|
||||
groupBy, having, sortOrder, limit);
|
||||
}
|
||||
maybePlayDebugNoise();
|
||||
long t1 = 0;
|
||||
if (mLog) {
|
||||
t1 = System.currentTimeMillis();
|
||||
@@ -300,7 +225,6 @@ public class DatabaseWrapper {
|
||||
if (mLog) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
maybePlayDebugNoise();
|
||||
final long retval =
|
||||
DatabaseUtils.queryNumEntries(mDatabase, table, selection, selectionArgs);
|
||||
if (mLog){
|
||||
@@ -313,14 +237,10 @@ public class DatabaseWrapper {
|
||||
}
|
||||
|
||||
public Cursor rawQuery(final String sql, final String[] args) {
|
||||
if (mExplainQueryPlanRegexp != null) {
|
||||
explainQueryPlan(mDatabase, sql, args);
|
||||
}
|
||||
long t1 = 0;
|
||||
if (mLog) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
maybePlayDebugNoise();
|
||||
final Cursor cursor = mDatabase.rawQuery(sql, args);
|
||||
if (mLog) {
|
||||
printTiming(
|
||||
@@ -336,7 +256,6 @@ public class DatabaseWrapper {
|
||||
if (mLog) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
maybePlayDebugNoise();
|
||||
int count = 0;
|
||||
try {
|
||||
count = mDatabase.update(table, values, selection, selectionArgs);
|
||||
@@ -356,7 +275,6 @@ public class DatabaseWrapper {
|
||||
if (mLog) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
maybePlayDebugNoise();
|
||||
int count = 0;
|
||||
try {
|
||||
count = mDatabase.delete(table, whereClause, whereArgs);
|
||||
@@ -378,7 +296,6 @@ public class DatabaseWrapper {
|
||||
if (mLog) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
maybePlayDebugNoise();
|
||||
long rowId = -1;
|
||||
try {
|
||||
rowId = mDatabase.insert(table, nullColumnHack, values);
|
||||
@@ -398,7 +315,6 @@ public class DatabaseWrapper {
|
||||
if (mLog) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
maybePlayDebugNoise();
|
||||
long rowId = -1;
|
||||
try {
|
||||
rowId = mDatabase.replace(table, nullColumnHack, values);
|
||||
@@ -421,7 +337,6 @@ public class DatabaseWrapper {
|
||||
if (mLog) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
maybePlayDebugNoise();
|
||||
try {
|
||||
mDatabase.execSQL(sql, bindArgs);
|
||||
} catch (SQLiteFullException ex) {
|
||||
@@ -439,7 +354,6 @@ public class DatabaseWrapper {
|
||||
if (mLog) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
maybePlayDebugNoise();
|
||||
try {
|
||||
mDatabase.execSQL(sql);
|
||||
} catch (SQLiteFullException ex) {
|
||||
@@ -457,7 +371,6 @@ public class DatabaseWrapper {
|
||||
if (mLog) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
maybePlayDebugNoise();
|
||||
final SQLiteStatement statement = mDatabase.compileStatement(sql);
|
||||
int rowsUpdated = 0;
|
||||
try {
|
||||
|
||||
@@ -51,7 +51,6 @@ import com.android.messaging.sms.MmsUtils;
|
||||
import com.android.messaging.ui.UIIntents;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.AvatarUriUtil;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.ContentType;
|
||||
import com.android.messaging.util.ConversationIdSet;
|
||||
@@ -1009,13 +1008,9 @@ public abstract class MessageNotificationState extends NotificationState {
|
||||
|
||||
private static int getMaxMessagesInConversationNotification() {
|
||||
if (!BugleNotifications.isWearCompanionAppInstalled()) {
|
||||
return BugleGservices.get().getInt(
|
||||
BugleGservicesKeys.MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION,
|
||||
BugleGservicesKeys.MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_DEFAULT);
|
||||
return BugleGservicesKeys.MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_DEFAULT;
|
||||
}
|
||||
return BugleGservices.get().getInt(
|
||||
BugleGservicesKeys.MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_WITH_WEARABLE,
|
||||
BugleGservicesKeys.MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_WITH_WEARABLE_DEFAULT);
|
||||
return BugleGservicesKeys.MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_WITH_WEARABLE_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -452,8 +452,6 @@ public class MessagingContentProvider extends ContentProvider {
|
||||
defaultSmsApp = "None";
|
||||
}
|
||||
writer.println("Default SMS app: " + defaultSmsApp);
|
||||
// Now dump logs
|
||||
LogUtil.dump(writer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +28,6 @@ import com.android.messaging.datamodel.action.SyncMessagesAction;
|
||||
import com.android.messaging.datamodel.data.ParticipantData;
|
||||
import com.android.messaging.sms.MmsUtils;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.BuglePrefs;
|
||||
import com.android.messaging.util.BuglePrefsKeys;
|
||||
@@ -206,13 +206,11 @@ public class SyncManager {
|
||||
* @return 0 if allowed to run now, else delay in ms
|
||||
*/
|
||||
public long delayUntilFullSync(final long startTimestamp) {
|
||||
final BugleGservices bugleGservices = BugleGservices.get();
|
||||
final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
|
||||
|
||||
final long lastFullSyncTime = prefs.getLong(BuglePrefsKeys.LAST_FULL_SYNC_TIME, -1L);
|
||||
final long smsFullSyncBackoffTimeMillis = bugleGservices.getLong(
|
||||
BugleGservicesKeys.SMS_FULL_SYNC_BACKOFF_TIME_MILLIS,
|
||||
BugleGservicesKeys.SMS_FULL_SYNC_BACKOFF_TIME_MILLIS_DEFAULT);
|
||||
final long smsFullSyncBackoffTimeMillis =
|
||||
BugleGservicesKeys.SMS_FULL_SYNC_BACKOFF_TIME_MILLIS_DEFAULT;
|
||||
final long noFullSyncBefore = (lastFullSyncTime < 0 ? startTimestamp :
|
||||
lastFullSyncTime + smsFullSyncBackoffTimeMillis);
|
||||
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS 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.messaging.datamodel.action;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.messaging.Factory;
|
||||
import com.android.messaging.datamodel.DatabaseHelper;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DumpDatabaseAction extends Action implements Parcelable {
|
||||
private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
|
||||
public static final String DUMP_NAME = "db_copy.db";
|
||||
private static final int BUFFER_SIZE = 16384;
|
||||
|
||||
/**
|
||||
* Copy the database to external storage
|
||||
*/
|
||||
public static void dumpDatabase() {
|
||||
final DumpDatabaseAction action = new DumpDatabaseAction();
|
||||
action.start();
|
||||
}
|
||||
|
||||
private DumpDatabaseAction() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object executeAction() {
|
||||
final Context context = Factory.get().getApplicationContext();
|
||||
final String dbName = DatabaseHelper.DATABASE_NAME;
|
||||
BufferedOutputStream bos = null;
|
||||
BufferedInputStream bis = null;
|
||||
|
||||
long originalSize = 0;
|
||||
final File inFile = context.getDatabasePath(dbName);
|
||||
if (inFile.exists() && inFile.isFile()) {
|
||||
originalSize = inFile.length();
|
||||
}
|
||||
final File outFile = DebugUtils.getDebugFile(DUMP_NAME, true);
|
||||
if (outFile != null) {
|
||||
int totalBytes = 0;
|
||||
try {
|
||||
bos = new BufferedOutputStream(new FileOutputStream(outFile));
|
||||
bis = new BufferedInputStream(new FileInputStream(inFile));
|
||||
|
||||
final byte[] buffer = new byte[BUFFER_SIZE];
|
||||
int bytesRead;
|
||||
while ((bytesRead = bis.read(buffer)) > 0) {
|
||||
bos.write(buffer, 0, bytesRead);
|
||||
totalBytes += bytesRead;
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
LogUtil.w(TAG, "Exception copying the database;"
|
||||
+ " destination may not be complete.", e);
|
||||
} finally {
|
||||
if (bos != null) {
|
||||
try {
|
||||
bos.close();
|
||||
} catch (final IOException e) {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
if (bis != null) {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (final IOException e) {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
DebugUtils.ensureReadable(outFile);
|
||||
LogUtil.i(TAG, "Dump complete; orig size: " + originalSize +
|
||||
", copy size: " + totalBytes);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private DumpDatabaseAction(final Parcel in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<DumpDatabaseAction> CREATOR
|
||||
= new Parcelable.Creator<DumpDatabaseAction>() {
|
||||
@Override
|
||||
public DumpDatabaseAction createFromParcel(final Parcel in) {
|
||||
return new DumpDatabaseAction(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DumpDatabaseAction[] newArray(final int size) {
|
||||
return new DumpDatabaseAction[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull final Parcel parcel, final int flags) {
|
||||
writeActionToParcel(parcel, flags);
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS 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.messaging.datamodel.action;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.Telephony.Threads;
|
||||
import android.provider.Telephony.ThreadsColumns;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.messaging.Factory;
|
||||
import com.android.messaging.mmslib.SqliteWrapper;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
|
||||
public class LogTelephonyDatabaseAction extends Action implements Parcelable {
|
||||
// Because we use sanitizePII, we should also use BUGLE_TAG
|
||||
private static final String TAG = LogUtil.BUGLE_TAG;
|
||||
|
||||
private static final String[] ALL_THREADS_PROJECTION = {
|
||||
Threads._ID,
|
||||
Threads.DATE,
|
||||
Threads.MESSAGE_COUNT,
|
||||
Threads.RECIPIENT_IDS,
|
||||
Threads.SNIPPET,
|
||||
Threads.SNIPPET_CHARSET,
|
||||
Threads.READ,
|
||||
Threads.ERROR,
|
||||
Threads.HAS_ATTACHMENT };
|
||||
|
||||
// Constants from the Telephony Database
|
||||
private static final int ID = 0;
|
||||
private static final int DATE = 1;
|
||||
private static final int MESSAGE_COUNT = 2;
|
||||
private static final int RECIPIENT_IDS = 3;
|
||||
private static final int SNIPPET = 4;
|
||||
private static final int SNIPPET_CHAR_SET = 5;
|
||||
private static final int READ = 6;
|
||||
private static final int ERROR = 7;
|
||||
private static final int HAS_ATTACHMENT = 8;
|
||||
|
||||
/**
|
||||
* Log telephony data to logcat
|
||||
*/
|
||||
public static void dumpDatabase() {
|
||||
final LogTelephonyDatabaseAction action = new LogTelephonyDatabaseAction();
|
||||
action.start();
|
||||
}
|
||||
|
||||
private LogTelephonyDatabaseAction() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object executeAction() {
|
||||
final Context context = Factory.get().getApplicationContext();
|
||||
|
||||
if (!DebugUtils.isDebugEnabled()) {
|
||||
LogUtil.e(TAG, "Can't log telephony database unless debugging is enabled");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
|
||||
LogUtil.w(TAG, "Can't log telephony database unless DEBUG is turned on for TAG: " +
|
||||
TAG);
|
||||
return null;
|
||||
}
|
||||
|
||||
LogUtil.d(TAG, "\n");
|
||||
LogUtil.d(TAG, "Dump of canoncial_addresses table");
|
||||
LogUtil.d(TAG, "*********************************");
|
||||
|
||||
Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
|
||||
Uri.parse("content://mms-sms/canonical-addresses"), null, null, null, null);
|
||||
|
||||
if (cursor == null) {
|
||||
LogUtil.w(TAG, "null Cursor in content://mms-sms/canonical-addresses");
|
||||
} else {
|
||||
try {
|
||||
while (cursor.moveToNext()) {
|
||||
long id = cursor.getLong(0);
|
||||
String number = cursor.getString(1);
|
||||
LogUtil.d(TAG, LogUtil.sanitizePII("id: " + id + " number: " + number));
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
LogUtil.d(TAG, "\n");
|
||||
LogUtil.d(TAG, "Dump of threads table");
|
||||
LogUtil.d(TAG, "*********************");
|
||||
|
||||
cursor = SqliteWrapper.query(context, context.getContentResolver(),
|
||||
Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build(),
|
||||
ALL_THREADS_PROJECTION, null, null, "date ASC");
|
||||
try {
|
||||
while (cursor.moveToNext()) {
|
||||
LogUtil.d(TAG, LogUtil.sanitizePII("threadId: " + cursor.getLong(ID) +
|
||||
" " + ThreadsColumns.DATE + " : " + cursor.getLong(DATE) +
|
||||
" " + ThreadsColumns.MESSAGE_COUNT + " : " + cursor.getInt(MESSAGE_COUNT) +
|
||||
" " + ThreadsColumns.SNIPPET + " : " + cursor.getString(SNIPPET) +
|
||||
" " + ThreadsColumns.READ + " : " + cursor.getInt(READ) +
|
||||
" " + ThreadsColumns.ERROR + " : " + cursor.getInt(ERROR) +
|
||||
" " + ThreadsColumns.HAS_ATTACHMENT + " : " +
|
||||
cursor.getInt(HAS_ATTACHMENT) +
|
||||
" " + ThreadsColumns.RECIPIENT_IDS + " : " +
|
||||
cursor.getString(RECIPIENT_IDS)));
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private LogTelephonyDatabaseAction(final Parcel in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<LogTelephonyDatabaseAction> CREATOR
|
||||
= new Parcelable.Creator<LogTelephonyDatabaseAction>() {
|
||||
@Override
|
||||
public LogTelephonyDatabaseAction createFromParcel(final Parcel in) {
|
||||
return new LogTelephonyDatabaseAction(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogTelephonyDatabaseAction[] newArray(final int size) {
|
||||
return new LogTelephonyDatabaseAction[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull final Parcel parcel, final int flags) {
|
||||
writeActionToParcel(parcel, flags);
|
||||
}
|
||||
}
|
||||
@@ -271,9 +271,6 @@ public class ProcessDownloadedMmsAction extends Action {
|
||||
if (downloadedData != null) {
|
||||
final RetrieveConf retrieveConf =
|
||||
MmsSender.parseRetrieveConf(downloadedData, subId);
|
||||
if (MmsUtils.isDumpMmsEnabled()) {
|
||||
MmsUtils.dumpPdu(downloadedData, retrieveConf);
|
||||
}
|
||||
if (retrieveConf != null) {
|
||||
// Insert the downloaded MMS into telephony
|
||||
final Uri notificationUri = actionParameters.getParcelable(
|
||||
|
||||
@@ -35,7 +35,6 @@ import com.android.messaging.datamodel.DatabaseWrapper;
|
||||
import com.android.messaging.datamodel.MessagingContentProvider;
|
||||
import com.android.messaging.datamodel.data.MessageData;
|
||||
import com.android.messaging.datamodel.data.ParticipantData;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.BuglePrefs;
|
||||
import com.android.messaging.util.BuglePrefsKeys;
|
||||
@@ -153,12 +152,8 @@ public class ProcessPendingMessagesAction extends Action implements Parcelable {
|
||||
|
||||
final ProcessPendingMessagesAction action = new ProcessPendingMessagesAction();
|
||||
action.actionParameters.putInt(KEY_SUB_ID, subId);
|
||||
final long initialBackoffMs = BugleGservices.get().getLong(
|
||||
BugleGservicesKeys.INITIAL_MESSAGE_RESEND_DELAY_MS,
|
||||
BugleGservicesKeys.INITIAL_MESSAGE_RESEND_DELAY_MS_DEFAULT);
|
||||
final long maxDelayMs = BugleGservices.get().getLong(
|
||||
BugleGservicesKeys.MAX_MESSAGE_RESEND_DELAY_MS,
|
||||
BugleGservicesKeys.MAX_MESSAGE_RESEND_DELAY_MS_DEFAULT);
|
||||
final long initialBackoffMs = BugleGservicesKeys.INITIAL_MESSAGE_RESEND_DELAY_MS_DEFAULT;
|
||||
final long maxDelayMs = BugleGservicesKeys.MAX_MESSAGE_RESEND_DELAY_MS_DEFAULT;
|
||||
long delayMs;
|
||||
long nextDelayMs = initialBackoffMs;
|
||||
do {
|
||||
|
||||
@@ -43,7 +43,6 @@ import com.android.messaging.sms.DatabaseMessages.MmsMessage;
|
||||
import com.android.messaging.sms.DatabaseMessages.SmsMessage;
|
||||
import com.android.messaging.sms.MmsUtils;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.BuglePrefs;
|
||||
import com.android.messaging.util.BuglePrefsKeys;
|
||||
@@ -76,10 +75,8 @@ public class SyncMessagesAction extends Action implements Parcelable {
|
||||
* Start a full sync (backed off a few seconds to avoid pulling sending/receiving messages).
|
||||
*/
|
||||
public static void fullSync() {
|
||||
final BugleGservices bugleGservices = BugleGservices.get();
|
||||
final long smsSyncBackoffTimeMillis = bugleGservices.getLong(
|
||||
BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS,
|
||||
BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS_DEFAULT);
|
||||
final long smsSyncBackoffTimeMillis =
|
||||
BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS_DEFAULT;
|
||||
|
||||
final long now = System.currentTimeMillis();
|
||||
// TODO: Could base this off most recent message in db but now should be okay...
|
||||
@@ -94,10 +91,8 @@ public class SyncMessagesAction extends Action implements Parcelable {
|
||||
* Start an incremental sync to pull messages since last sync (backed off a few seconds)..
|
||||
*/
|
||||
public static void sync() {
|
||||
final BugleGservices bugleGservices = BugleGservices.get();
|
||||
final long smsSyncBackoffTimeMillis = bugleGservices.getLong(
|
||||
BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS,
|
||||
BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS_DEFAULT);
|
||||
final long smsSyncBackoffTimeMillis =
|
||||
BugleGservicesKeys.SMS_SYNC_BACKOFF_TIME_MILLIS_DEFAULT;
|
||||
|
||||
final long now = System.currentTimeMillis();
|
||||
// TODO: Could base this off most recent message in db but now should be okay...
|
||||
@@ -195,20 +190,16 @@ public class SyncMessagesAction extends Action implements Parcelable {
|
||||
|
||||
@Override
|
||||
protected Bundle doBackgroundWork() {
|
||||
final BugleGservices bugleGservices = BugleGservices.get();
|
||||
final DatabaseWrapper db = DataModel.get().getDatabase();
|
||||
|
||||
final int maxMessagesToScan = bugleGservices.getInt(
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_MAX_MESSAGES_TO_SCAN,
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_MAX_MESSAGES_TO_SCAN_DEFAULT);
|
||||
final int maxMessagesToScan =
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_MAX_MESSAGES_TO_SCAN_DEFAULT;
|
||||
|
||||
final int initialMaxMessagesToUpdate = actionParameters.getInt(KEY_MAX_UPDATE);
|
||||
final int smsSyncSubsequentBatchSizeMin = bugleGservices.getInt(
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MIN,
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MIN_DEFAULT);
|
||||
final int smsSyncSubsequentBatchSizeMax = bugleGservices.getInt(
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MAX,
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MAX_DEFAULT);
|
||||
final int smsSyncSubsequentBatchSizeMin =
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MIN_DEFAULT;
|
||||
final int smsSyncSubsequentBatchSizeMax =
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_SIZE_MAX_DEFAULT;
|
||||
|
||||
// Cap sync size to GServices limits
|
||||
final int maxMessagesToUpdate = Math.max(smsSyncSubsequentBatchSizeMin,
|
||||
@@ -512,10 +503,8 @@ public class SyncMessagesAction extends Action implements Parcelable {
|
||||
* @return Target number of messages to sync for next batch
|
||||
*/
|
||||
private static int nextBatchSize(final int messagesUpdated, final long txnTimeMillis) {
|
||||
final BugleGservices bugleGservices = BugleGservices.get();
|
||||
final long smsSyncSubsequentBatchTimeLimitMillis = bugleGservices.getLong(
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_TIME_LIMIT_MILLIS,
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_TIME_LIMIT_MILLIS_DEFAULT);
|
||||
final long smsSyncSubsequentBatchTimeLimitMillis =
|
||||
BugleGservicesKeys.SMS_SYNC_BATCH_TIME_LIMIT_MILLIS_DEFAULT;
|
||||
|
||||
if (txnTimeMillis <= 0) {
|
||||
return 0;
|
||||
|
||||
@@ -30,7 +30,6 @@ import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
|
||||
import com.android.messaging.datamodel.DatabaseHelper.PartColumns;
|
||||
import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.ContentType;
|
||||
import com.android.messaging.util.Dates;
|
||||
@@ -396,9 +395,7 @@ public class ConversationMessageData {
|
||||
if (!TextUtils.isEmpty(firstTextPart)) {
|
||||
sb.append(firstTextPart);
|
||||
}
|
||||
separator = BugleGservices.get().getString(
|
||||
BugleGservicesKeys.MMS_TEXT_CONCAT_SEPARATOR,
|
||||
BugleGservicesKeys.MMS_TEXT_CONCAT_SEPARATOR_DEFAULT);
|
||||
separator = BugleGservicesKeys.MMS_TEXT_CONCAT_SEPARATOR_DEFAULT;
|
||||
}
|
||||
final String partText = part.getText();
|
||||
if (!TextUtils.isEmpty(partText)) {
|
||||
|
||||
@@ -34,7 +34,6 @@ import com.android.messaging.sms.MmsUtils;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
|
||||
import com.android.messaging.util.Assert.RunsOnMainThread;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
@@ -471,9 +470,7 @@ public class DraftMessageData extends BindableData implements ReadDraftDataActio
|
||||
}
|
||||
|
||||
private int getAttachmentLimit() {
|
||||
return BugleGservices.get().getInt(
|
||||
BugleGservicesKeys.MMS_ATTACHMENT_LIMIT,
|
||||
BugleGservicesKeys.MMS_ATTACHMENT_LIMIT_DEFAULT);
|
||||
return BugleGservicesKeys.MMS_ATTACHMENT_LIMIT_DEFAULT;
|
||||
}
|
||||
|
||||
public void removeAttachment(final MessagePartData attachment) {
|
||||
|
||||
@@ -32,10 +32,8 @@ import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
|
||||
import com.android.messaging.datamodel.DatabaseWrapper;
|
||||
import com.android.messaging.sms.MmsUtils;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.Dates;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
import com.android.messaging.util.OsUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -564,17 +562,13 @@ public class MessageData implements Parcelable {
|
||||
}
|
||||
|
||||
public final boolean getInResendWindow(final long now) {
|
||||
final long maxAgeToResend = BugleGservices.get().getLong(
|
||||
BugleGservicesKeys.MESSAGE_RESEND_TIMEOUT_MS,
|
||||
BugleGservicesKeys.MESSAGE_RESEND_TIMEOUT_MS_DEFAULT);
|
||||
final long maxAgeToResend = BugleGservicesKeys.MESSAGE_RESEND_TIMEOUT_MS_DEFAULT;
|
||||
final long age = now - mRetryStartTimestamp;
|
||||
return age < maxAgeToResend;
|
||||
}
|
||||
|
||||
public final boolean getInDownloadWindow(final long now) {
|
||||
final long maxAgeToRedownload = BugleGservices.get().getLong(
|
||||
BugleGservicesKeys.MESSAGE_DOWNLOAD_TIMEOUT_MS,
|
||||
BugleGservicesKeys.MESSAGE_DOWNLOAD_TIMEOUT_MS_DEFAULT);
|
||||
final long maxAgeToRedownload = BugleGservicesKeys.MESSAGE_DOWNLOAD_TIMEOUT_MS_DEFAULT;
|
||||
final long age = now - mRetryStartTimestamp;
|
||||
return age < maxAgeToRedownload;
|
||||
}
|
||||
@@ -586,11 +580,9 @@ public class MessageData implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
// Should show option for manual download if status is manual download or failed
|
||||
// If debug is enabled, allow to download an expired or unavailable message.
|
||||
return (status == BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED ||
|
||||
status == BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD ||
|
||||
// If debug is enabled, allow to download an expired or unavailable message.
|
||||
(DebugUtils.isDebugEnabled()
|
||||
&& status == BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE));
|
||||
status == BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD);
|
||||
}
|
||||
|
||||
public boolean canDownloadMessage() {
|
||||
@@ -611,11 +603,9 @@ public class MessageData implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
// Can redownload if status is manual download not started or download failed
|
||||
// If debug is enabled, allow to download an expired or unavailable message.
|
||||
return (mStatus == BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED ||
|
||||
mStatus == BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD ||
|
||||
// If debug is enabled, allow to download an expired or unavailable message.
|
||||
(DebugUtils.isDebugEnabled()
|
||||
&& mStatus == BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE));
|
||||
mStatus == BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD);
|
||||
}
|
||||
|
||||
static boolean getShowResendMessage(final int status) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +35,6 @@ import androidx.core.app.NotificationManagerCompat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import com.android.messaging.Factory;
|
||||
import com.android.messaging.R;
|
||||
@@ -44,9 +44,6 @@ import com.android.messaging.datamodel.NoConfirmationSmsSendService;
|
||||
import com.android.messaging.datamodel.action.ReceiveSmsMessageAction;
|
||||
import com.android.messaging.sms.MmsUtils;
|
||||
import com.android.messaging.ui.UIIntents;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
import com.android.messaging.util.NotificationsUtil;
|
||||
import com.android.messaging.util.OsUtil;
|
||||
@@ -125,10 +122,6 @@ public final class SmsReceiver extends BroadcastReceiver {
|
||||
int subId = PhoneUtils.getDefault().getEffectiveIncomingSubIdFromSystem(
|
||||
intent, EXTRA_SUB_ID);
|
||||
deliverSmsMessages(context, subId, errorCode, messages);
|
||||
if (MmsUtils.isDumpSmsEnabled()) {
|
||||
final String format = intent.getStringExtra("format");
|
||||
DebugUtils.dumpSms(messages[0].getTimestampMillis(), messages, format);
|
||||
}
|
||||
}
|
||||
|
||||
public static void deliverSmsMessages(final Context context, final int subId,
|
||||
@@ -148,8 +141,7 @@ public final class SmsReceiver extends BroadcastReceiver {
|
||||
messageValues.put(Sms.Inbox.SEEN, 0);
|
||||
messageValues.put(Sms.SUBSCRIPTION_ID, subId);
|
||||
|
||||
if (messages[0].getMessageClass() == android.telephony.SmsMessage.MessageClass.CLASS_0 ||
|
||||
DebugUtils.debugClassZeroSmsEnabled()) {
|
||||
if (messages[0].getMessageClass() == android.telephony.SmsMessage.MessageClass.CLASS_0) {
|
||||
Factory.get().getUIIntents().launchClassZeroActivity(context, messageValues);
|
||||
} else {
|
||||
final ReceiveSmsMessageAction action = new ReceiveSmsMessageAction(messageValues);
|
||||
@@ -228,30 +220,6 @@ public final class SmsReceiver extends BroadcastReceiver {
|
||||
return Factory.get().getApplicationContext().getPackageName() + ":secondaryuser";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile all of the patterns we check for to ignore system SMS messages.
|
||||
*/
|
||||
private static void compileIgnoreSmsPatterns() {
|
||||
// Get the pattern set from GServices
|
||||
final String smsIgnoreRegex = BugleGservices.get().getString(
|
||||
BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX,
|
||||
BugleGservicesKeys.SMS_IGNORE_MESSAGE_REGEX_DEFAULT);
|
||||
if (smsIgnoreRegex != null) {
|
||||
final String[] ignoreSmsExpressions = smsIgnoreRegex.split("\n");
|
||||
if (ignoreSmsExpressions.length != 0) {
|
||||
sIgnoreSmsPatterns = new ArrayList<Pattern>();
|
||||
for (int i = 0; i < ignoreSmsExpressions.length; i++) {
|
||||
try {
|
||||
sIgnoreSmsPatterns.add(Pattern.compile(ignoreSmsExpressions[i]));
|
||||
} catch (PatternSyntaxException e) {
|
||||
LogUtil.e(TAG, "compileIgnoreSmsPatterns: Skipping bad expression: " +
|
||||
ignoreSmsExpressions[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SMS messages from the specified SMS intent.
|
||||
* @return the messages. If there is an error or the message should be ignored, return null.
|
||||
@@ -263,27 +231,6 @@ public final class SmsReceiver extends BroadcastReceiver {
|
||||
if (messages == null || messages.length < 1) {
|
||||
return null;
|
||||
}
|
||||
// Sometimes, SmsMessage.mWrappedSmsMessage is null causing NPE when we access
|
||||
// the methods on it although the SmsMessage itself is not null. So do this check
|
||||
// before we do anything on the parsed SmsMessages.
|
||||
try {
|
||||
final String messageBody = messages[0].getDisplayMessageBody();
|
||||
if (messageBody != null) {
|
||||
// Compile patterns if necessary
|
||||
if (sIgnoreSmsPatterns == null) {
|
||||
compileIgnoreSmsPatterns();
|
||||
}
|
||||
// Check against filters
|
||||
for (final Pattern pattern : sIgnoreSmsPatterns) {
|
||||
if (pattern.matcher(messageBody).matches()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final NullPointerException e) {
|
||||
LogUtil.e(TAG, "shouldIgnoreMessage: NPE inside SmsMessage");
|
||||
return null;
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,6 @@ import android.util.SparseArray;
|
||||
|
||||
import com.android.messaging.datamodel.data.ParticipantData;
|
||||
import com.android.messaging.mmslib.SqliteWrapper;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
|
||||
@@ -336,11 +334,6 @@ public class BugleApnSettingsLoader implements ApnSettingsLoader {
|
||||
}
|
||||
|
||||
private void loadLocked(final int subId, final String apnName, final List<Apn> apns) {
|
||||
// Try Gservices first
|
||||
loadFromGservices(apns);
|
||||
if (apns.size() > 0) {
|
||||
return;
|
||||
}
|
||||
// Try system APN table
|
||||
loadFromSystem(subId, apnName, apns);
|
||||
if (apns.size() > 0) {
|
||||
@@ -353,26 +346,6 @@ public class BugleApnSettingsLoader implements ApnSettingsLoader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load from Gservices if APN setting is set in Gservices
|
||||
*
|
||||
* @param apns the list used to return results
|
||||
*/
|
||||
private void loadFromGservices(final List<Apn> apns) {
|
||||
final BugleGservices gservices = BugleGservices.get();
|
||||
final String mmsc = gservices.getString(BugleGservicesKeys.MMS_MMSC, null);
|
||||
if (TextUtils.isEmpty(mmsc)) {
|
||||
return;
|
||||
}
|
||||
LogUtil.i(LogUtil.BUGLE_TAG, "Loading APNs from gservices");
|
||||
final String proxy = gservices.getString(BugleGservicesKeys.MMS_PROXY_ADDRESS, null);
|
||||
final int port = gservices.getInt(BugleGservicesKeys.MMS_PROXY_PORT, -1);
|
||||
final Apn apn = BaseApn.from("mms", mmsc, proxy, Integer.toString(port));
|
||||
if (apn != null) {
|
||||
apns.add(apn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load matching APNs from telephony provider.
|
||||
* We try different combinations of the query to work around some platform quirks.
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.support.v7.mms.UserAgentInfoLoader;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
import com.android.messaging.util.VersionUtil;
|
||||
@@ -86,9 +85,7 @@ public class BugleUserAgentInfoLoader implements UserAgentInfoLoader {
|
||||
}
|
||||
// if the UAProfUrl isn't set, get it from Gservices
|
||||
if (TextUtils.isEmpty(mUAProfUrl)) {
|
||||
mUAProfUrl = BugleGservices.get().getString(
|
||||
BugleGservicesKeys.MMS_UA_PROFILE_URL,
|
||||
BugleGservicesKeys.MMS_UA_PROFILE_URL_DEFAULT);
|
||||
mUAProfUrl = BugleGservicesKeys.MMS_UA_PROFILE_URL_DEFAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@ import com.android.messaging.mmslib.pdu.SendConf;
|
||||
import com.android.messaging.mmslib.pdu.SendReq;
|
||||
import com.android.messaging.sms.SmsSender.SendResult;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.BuglePrefs;
|
||||
import com.android.messaging.util.ContentType;
|
||||
@@ -1538,44 +1537,6 @@ public class MmsUtils {
|
||||
sUseSystemApn = turnOn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if we should dump sms, based on both the setting and the global debug
|
||||
* flag
|
||||
*
|
||||
* @return if dump sms is enabled
|
||||
*/
|
||||
public static boolean isDumpSmsEnabled() {
|
||||
if (!DebugUtils.isDebugEnabled()) {
|
||||
return false;
|
||||
}
|
||||
return getDumpSmsOrMmsPref(R.string.dump_sms_pref_key, R.bool.dump_sms_pref_default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if we should dump mms, based on both the setting and the global debug
|
||||
* flag
|
||||
*
|
||||
* @return if dump mms is enabled
|
||||
*/
|
||||
public static boolean isDumpMmsEnabled() {
|
||||
if (!DebugUtils.isDebugEnabled()) {
|
||||
return false;
|
||||
}
|
||||
return getDumpSmsOrMmsPref(R.string.dump_mms_pref_key, R.bool.dump_mms_pref_default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the value of dump sms or mms setting preference
|
||||
*/
|
||||
private static boolean getDumpSmsOrMmsPref(final int prefKeyRes, final int defaultKeyRes) {
|
||||
final Context context = Factory.get().getApplicationContext();
|
||||
final Resources resources = context.getResources();
|
||||
final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
|
||||
final String key = resources.getString(prefKeyRes);
|
||||
final boolean defaultValue = resources.getBoolean(defaultKeyRes);
|
||||
return prefs.getBoolean(key, defaultValue);
|
||||
}
|
||||
|
||||
public static final Uri MMS_PART_CONTENT_URI = Uri.parse("content://mms/part");
|
||||
|
||||
/**
|
||||
@@ -1731,9 +1692,7 @@ public class MmsUtils {
|
||||
public static MessagePartData createMmsMessagePart(final DatabaseMessages.MmsPart part) {
|
||||
MessagePartData messagePart = null;
|
||||
if (part.isText()) {
|
||||
final int mmsTextLengthLimit =
|
||||
BugleGservices.get().getInt(BugleGservicesKeys.MMS_TEXT_LIMIT,
|
||||
BugleGservicesKeys.MMS_TEXT_LIMIT_DEFAULT);
|
||||
final int mmsTextLengthLimit = BugleGservicesKeys.MMS_TEXT_LIMIT_DEFAULT;
|
||||
String text = part.mText;
|
||||
if (text != null && text.length() > mmsTextLengthLimit) {
|
||||
// Limit the text to a reasonable value. We ran into a situation where a vcard
|
||||
@@ -1806,44 +1765,30 @@ public class MmsUtils {
|
||||
int status = MMS_REQUEST_MANUAL_RETRY;
|
||||
try {
|
||||
RetrieveConf retrieveConf = null;
|
||||
if (DebugUtils.isDebugEnabled() &&
|
||||
MediaScratchFileProvider
|
||||
.isMediaScratchSpaceUri(Uri.parse(contentLocation))) {
|
||||
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
|
||||
LogUtil.d(TAG, "MmsUtils: Reading MMS from dump file: " + contentLocation);
|
||||
}
|
||||
final String fileName = Uri.parse(contentLocation).getPathSegments().get(1);
|
||||
final byte[] data = DebugUtils.receiveFromDumpFile(fileName);
|
||||
retrieveConf = receiveFromDumpFile(data);
|
||||
} else {
|
||||
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
|
||||
LogUtil.d(TAG, "MmsUtils: Downloading MMS via MMS lib API; notification "
|
||||
+ "message: " + notificationUri);
|
||||
}
|
||||
if (subId < 0) {
|
||||
LogUtil.e(TAG, "MmsUtils: Incoming MMS came from unknown SIM");
|
||||
throw new MmsFailureException(MMS_REQUEST_NO_RETRY,
|
||||
"Message from unknown SIM");
|
||||
}
|
||||
if (extras == null) {
|
||||
extras = new Bundle();
|
||||
}
|
||||
extras.putParcelable(DownloadMmsAction.EXTRA_NOTIFICATION_URI, notificationUri);
|
||||
extras.putInt(DownloadMmsAction.EXTRA_SUB_ID, subId);
|
||||
extras.putString(DownloadMmsAction.EXTRA_SUB_PHONE_NUMBER, subPhoneNumber);
|
||||
extras.putString(DownloadMmsAction.EXTRA_TRANSACTION_ID, transactionId);
|
||||
extras.putString(DownloadMmsAction.EXTRA_CONTENT_LOCATION, contentLocation);
|
||||
extras.putBoolean(DownloadMmsAction.EXTRA_AUTO_DOWNLOAD, autoDownload);
|
||||
extras.putLong(DownloadMmsAction.EXTRA_RECEIVED_TIMESTAMP,
|
||||
receivedTimestampInSeconds);
|
||||
extras.putLong(DownloadMmsAction.EXTRA_EXPIRY, expiry);
|
||||
|
||||
MmsSender.downloadMms(context, subId, contentLocation, extras);
|
||||
return STATUS_PENDING; // Download happens asynchronously; no status to return
|
||||
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
|
||||
LogUtil.d(TAG, "MmsUtils: Downloading MMS via MMS lib API; notification "
|
||||
+ "message: " + notificationUri);
|
||||
}
|
||||
return insertDownloadedMessageAndSendResponse(context, notificationUri, subId,
|
||||
subPhoneNumber, transactionId, contentLocation, autoDownload,
|
||||
receivedTimestampInSeconds, expiry, retrieveConf);
|
||||
if (subId < 0) {
|
||||
LogUtil.e(TAG, "MmsUtils: Incoming MMS came from unknown SIM");
|
||||
throw new MmsFailureException(MMS_REQUEST_NO_RETRY,
|
||||
"Message from unknown SIM");
|
||||
}
|
||||
if (extras == null) {
|
||||
extras = new Bundle();
|
||||
}
|
||||
extras.putParcelable(DownloadMmsAction.EXTRA_NOTIFICATION_URI, notificationUri);
|
||||
extras.putInt(DownloadMmsAction.EXTRA_SUB_ID, subId);
|
||||
extras.putString(DownloadMmsAction.EXTRA_SUB_PHONE_NUMBER, subPhoneNumber);
|
||||
extras.putString(DownloadMmsAction.EXTRA_TRANSACTION_ID, transactionId);
|
||||
extras.putString(DownloadMmsAction.EXTRA_CONTENT_LOCATION, contentLocation);
|
||||
extras.putBoolean(DownloadMmsAction.EXTRA_AUTO_DOWNLOAD, autoDownload);
|
||||
extras.putLong(DownloadMmsAction.EXTRA_RECEIVED_TIMESTAMP,
|
||||
receivedTimestampInSeconds);
|
||||
extras.putLong(DownloadMmsAction.EXTRA_EXPIRY, expiry);
|
||||
|
||||
MmsSender.downloadMms(context, subId, contentLocation, extras);
|
||||
return STATUS_PENDING; // Download happens asynchronously; no status to return
|
||||
|
||||
} catch (final MmsFailureException e) {
|
||||
LogUtil.e(TAG, "MmsUtils: failed to download message " + notificationUri, e);
|
||||
|
||||
@@ -33,7 +33,6 @@ import com.android.messaging.Factory;
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.receiver.SendStatusReceiver;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
@@ -225,9 +224,8 @@ public class SmsSender {
|
||||
context, subId, dest, messages, serviceCenter, requireDeliveryReport, messageUri);
|
||||
// Wait for pending intent to come back
|
||||
synchronized (pendingResult) {
|
||||
final long smsSendTimeoutInMillis = BugleGservices.get().getLong(
|
||||
BugleGservicesKeys.SMS_SEND_TIMEOUT_IN_MILLIS,
|
||||
BugleGservicesKeys.SMS_SEND_TIMEOUT_IN_MILLIS_DEFAULT);
|
||||
final long smsSendTimeoutInMillis =
|
||||
BugleGservicesKeys.SMS_SEND_TIMEOUT_IN_MILLIS_DEFAULT;
|
||||
final long beginTime = SystemClock.elapsedRealtime();
|
||||
long waitTime = smsSendTimeoutInMillis;
|
||||
// We could possibly be woken up while still pending
|
||||
|
||||
@@ -154,11 +154,6 @@ public abstract class UIIntents {
|
||||
public abstract void launchCreateNewConversationActivity(final Context context,
|
||||
final MessageData draft);
|
||||
|
||||
/**
|
||||
* Launch debug activity to set MMS config options.
|
||||
*/
|
||||
public abstract void launchDebugMmsConfigActivity(final Context context);
|
||||
|
||||
/**
|
||||
* Launch an activity to change settings.
|
||||
*/
|
||||
@@ -325,16 +320,6 @@ public abstract class UIIntents {
|
||||
public abstract PendingIntent getPendingIntentForSecondaryUserNewMessageNotification(
|
||||
final Context context);
|
||||
|
||||
/**
|
||||
* Get an intent for showing the APN editor.
|
||||
*/
|
||||
public abstract Intent getApnEditorIntent(final Context context, final String rowId, int subId);
|
||||
|
||||
/**
|
||||
* Get an intent for showing the APN settings.
|
||||
*/
|
||||
public abstract Intent getApnSettingsIntent(final Context context, final int subId);
|
||||
|
||||
/**
|
||||
* Get an intent for showing advanced settings.
|
||||
*/
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.app.role.RoleManager;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ClipData;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -34,7 +33,7 @@ import android.os.Bundle;
|
||||
import android.provider.ContactsContract.Contacts;
|
||||
import android.provider.ContactsContract.Intents;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.Telephony;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.TaskStackBuilder;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
@@ -50,8 +49,6 @@ import com.android.messaging.datamodel.data.MessagePartData;
|
||||
import com.android.messaging.datamodel.data.ParticipantData;
|
||||
import com.android.messaging.receiver.NotificationReceiver;
|
||||
import com.android.messaging.sms.MmsSmsUtils;
|
||||
import com.android.messaging.ui.appsettings.ApnEditorActivity;
|
||||
import com.android.messaging.ui.appsettings.ApnSettingsActivity;
|
||||
import com.android.messaging.ui.appsettings.ApplicationSettingsActivity;
|
||||
import com.android.messaging.ui.appsettings.PerSubscriptionSettingsActivity;
|
||||
import com.android.messaging.ui.appsettings.SettingsActivity;
|
||||
@@ -62,7 +59,6 @@ import com.android.messaging.ui.conversationlist.ArchivedConversationListActivit
|
||||
import com.android.messaging.ui.conversationlist.ConversationListActivity;
|
||||
import com.android.messaging.ui.conversationlist.ForwardMessageActivity;
|
||||
import com.android.messaging.ui.conversationsettings.PeopleAndOptionsActivity;
|
||||
import com.android.messaging.ui.debug.DebugMmsConfigActivity;
|
||||
import com.android.messaging.ui.photoviewer.BuglePhotoViewActivity;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.ContentType;
|
||||
@@ -192,11 +188,6 @@ public class UIIntentsImpl extends UIIntents {
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchDebugMmsConfigActivity(final Context context) {
|
||||
context.startActivity(new Intent(context, DebugMmsConfigActivity.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchAddContactActivity(final Context context, final String destination) {
|
||||
final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
|
||||
@@ -449,21 +440,6 @@ public class UIIntentsImpl extends UIIntents {
|
||||
return getPendingIntentForConversationListActivity(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getApnEditorIntent(final Context context, final String rowId, final int subId) {
|
||||
final Intent intent = new Intent(context, ApnEditorActivity.class);
|
||||
intent.putExtra(UI_INTENT_EXTRA_APN_ROW_ID, rowId);
|
||||
intent.putExtra(UI_INTENT_EXTRA_SUB_ID, subId);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getApnSettingsIntent(final Context context, final int subId) {
|
||||
final Intent intent = new Intent(context, ApnSettingsActivity.class)
|
||||
.putExtra(UI_INTENT_EXTRA_SUB_ID, subId);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getAdvancedSettingsIntent(final Context context) {
|
||||
return getPerSubscriptionSettingsIntent(context, ParticipantData.DEFAULT_SELF_SUB_ID, null);
|
||||
|
||||
@@ -1,466 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS 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.messaging.ui.appsettings;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.provider.Telephony;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.NavUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.datamodel.data.ParticipantData;
|
||||
import com.android.messaging.sms.ApnDatabase;
|
||||
import com.android.messaging.sms.BugleApnSettingsLoader;
|
||||
import com.android.messaging.ui.BugleActionBarActivity;
|
||||
import com.android.messaging.ui.UIIntents;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
|
||||
public class ApnEditorActivity extends BugleActionBarActivity {
|
||||
private static final int ERROR_DIALOG_ID = 0;
|
||||
private static final String ERROR_MESSAGE_KEY = "error_msg";
|
||||
private ApnEditorFragment mApnEditorFragment;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
// Display the fragment as the main content.
|
||||
mApnEditorFragment = new ApnEditorFragment();
|
||||
mApnEditorFragment.setSubId(getIntent().getIntExtra(UIIntents.UI_INTENT_EXTRA_SUB_ID,
|
||||
ParticipantData.DEFAULT_SELF_SUB_ID));
|
||||
getFragmentManager().beginTransaction()
|
||||
.replace(android.R.id.content, mApnEditorFragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
NavUtils.navigateUpFromSameTask(this);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(int id, Bundle args) {
|
||||
|
||||
if (id == ERROR_DIALOG_ID) {
|
||||
String msg = args.getString(ERROR_MESSAGE_KEY);
|
||||
|
||||
return new AlertDialog.Builder(this)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setMessage(msg)
|
||||
.create();
|
||||
}
|
||||
|
||||
return super.onCreateDialog(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_BACK: {
|
||||
if (mApnEditorFragment.validateAndSave(false)) {
|
||||
finish();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
|
||||
super.onPrepareDialog(id, dialog);
|
||||
|
||||
if (id == ERROR_DIALOG_ID) {
|
||||
final String msg = args.getString(ERROR_MESSAGE_KEY);
|
||||
|
||||
if (msg != null) {
|
||||
((AlertDialog) dialog).setMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ApnEditorFragment extends PreferenceFragment implements
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private static final String SAVED_POS = "pos";
|
||||
|
||||
private static final int MENU_DELETE = Menu.FIRST;
|
||||
private static final int MENU_SAVE = Menu.FIRST + 1;
|
||||
private static final int MENU_CANCEL = Menu.FIRST + 2;
|
||||
|
||||
private EditTextPreference mMmsProxy;
|
||||
private EditTextPreference mMmsPort;
|
||||
private EditTextPreference mName;
|
||||
private EditTextPreference mMmsc;
|
||||
private EditTextPreference mMcc;
|
||||
private EditTextPreference mMnc;
|
||||
private static String sNotSet;
|
||||
|
||||
private String mCurMnc;
|
||||
private String mCurMcc;
|
||||
|
||||
private Cursor mCursor;
|
||||
private boolean mNewApn;
|
||||
private boolean mFirstTime;
|
||||
private String mCurrentId;
|
||||
|
||||
private int mSubId;
|
||||
|
||||
/**
|
||||
* Standard projection for the interesting columns of a normal note.
|
||||
*/
|
||||
private static final String[] sProjection = new String[] {
|
||||
Telephony.Carriers._ID, // 0
|
||||
Telephony.Carriers.NAME, // 1
|
||||
Telephony.Carriers.MMSC, // 2
|
||||
Telephony.Carriers.MCC, // 3
|
||||
Telephony.Carriers.MNC, // 4
|
||||
Telephony.Carriers.NUMERIC, // 5
|
||||
Telephony.Carriers.MMSPROXY, // 6
|
||||
Telephony.Carriers.MMSPORT, // 7
|
||||
Telephony.Carriers.TYPE, // 8
|
||||
};
|
||||
|
||||
private static final int ID_INDEX = 0;
|
||||
private static final int NAME_INDEX = 1;
|
||||
private static final int MMSC_INDEX = 2;
|
||||
private static final int MCC_INDEX = 3;
|
||||
private static final int MNC_INDEX = 4;
|
||||
private static final int NUMERIC_INDEX = 5;
|
||||
private static final int MMSPROXY_INDEX = 6;
|
||||
private static final int MMSPORT_INDEX = 7;
|
||||
private static final int TYPE_INDEX = 8;
|
||||
|
||||
private SQLiteDatabase mDatabase;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.apn_editor);
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
sNotSet = getResources().getString(R.string.apn_not_set);
|
||||
mName = (EditTextPreference) findPreference("apn_name");
|
||||
mMmsProxy = (EditTextPreference) findPreference("apn_mms_proxy");
|
||||
mMmsPort = (EditTextPreference) findPreference("apn_mms_port");
|
||||
mMmsc = (EditTextPreference) findPreference("apn_mmsc");
|
||||
mMcc = (EditTextPreference) findPreference("apn_mcc");
|
||||
mMnc = (EditTextPreference) findPreference("apn_mnc");
|
||||
|
||||
final Intent intent = getActivity().getIntent();
|
||||
|
||||
mFirstTime = savedInstanceState == null;
|
||||
mCurrentId = intent.getStringExtra(UIIntents.UI_INTENT_EXTRA_APN_ROW_ID);
|
||||
mNewApn = mCurrentId == null;
|
||||
|
||||
mDatabase = ApnDatabase.getApnDatabase().getWritableDatabase();
|
||||
|
||||
if (mNewApn) {
|
||||
fillUi();
|
||||
} else {
|
||||
// Do initial query not on the UI thread
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
if (mCurrentId != null) {
|
||||
String selection = Telephony.Carriers._ID + " =?";
|
||||
String[] selectionArgs = new String[]{ mCurrentId };
|
||||
mCursor = mDatabase.query(ApnDatabase.APN_TABLE, sProjection, selection,
|
||||
selectionArgs, null, null, null, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
if (mCursor == null) {
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
mCursor.moveToFirst();
|
||||
|
||||
fillUi();
|
||||
}
|
||||
}.execute((Void) null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mCursor != null) {
|
||||
mCursor.close();
|
||||
mCursor = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getPreferenceScreen().getSharedPreferences()
|
||||
.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
getPreferenceScreen().getSharedPreferences()
|
||||
.unregisterOnSharedPreferenceChangeListener(this);
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
public void setSubId(final int subId) {
|
||||
mSubId = subId;
|
||||
}
|
||||
|
||||
private void fillUi() {
|
||||
if (mNewApn) {
|
||||
mMcc.setText(null);
|
||||
mMnc.setText(null);
|
||||
String numeric = PhoneUtils.get(mSubId).getSimOperatorNumeric();
|
||||
// MCC is first 3 chars and then in 2 - 3 chars of MNC
|
||||
if (numeric != null && numeric.length() > 4) {
|
||||
// Country code
|
||||
String mcc = numeric.substring(0, 3);
|
||||
// Network code
|
||||
String mnc = numeric.substring(3);
|
||||
// Auto populate MNC and MCC for new entries, based on what SIM reports
|
||||
mMcc.setText(mcc);
|
||||
mMnc.setText(mnc);
|
||||
mCurMnc = mnc;
|
||||
mCurMcc = mcc;
|
||||
}
|
||||
mName.setText(null);
|
||||
mMmsProxy.setText(null);
|
||||
mMmsPort.setText(null);
|
||||
mMmsc.setText(null);
|
||||
} else if (mFirstTime) {
|
||||
mFirstTime = false;
|
||||
// Fill in all the values from the db in both text editor and summary
|
||||
mName.setText(mCursor.getString(NAME_INDEX));
|
||||
mMmsProxy.setText(mCursor.getString(MMSPROXY_INDEX));
|
||||
mMmsPort.setText(mCursor.getString(MMSPORT_INDEX));
|
||||
mMmsc.setText(mCursor.getString(MMSC_INDEX));
|
||||
mMcc.setText(mCursor.getString(MCC_INDEX));
|
||||
mMnc.setText(mCursor.getString(MNC_INDEX));
|
||||
}
|
||||
|
||||
mName.setSummary(checkNull(mName.getText()));
|
||||
mMmsProxy.setSummary(checkNull(mMmsProxy.getText()));
|
||||
mMmsPort.setSummary(checkNull(mMmsPort.getText()));
|
||||
mMmsc.setSummary(checkNull(mMmsc.getText()));
|
||||
mMcc.setSummary(checkNull(mMcc.getText()));
|
||||
mMnc.setSummary(checkNull(mMnc.getText()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
// If it's a new APN, then cancel will delete the new entry in onPause
|
||||
if (!mNewApn) {
|
||||
menu.add(0, MENU_DELETE, 0, R.string.menu_delete_apn)
|
||||
.setIcon(R.drawable.ic_delete_small_dark);
|
||||
}
|
||||
menu.add(0, MENU_SAVE, 0, R.string.menu_save_apn)
|
||||
.setIcon(android.R.drawable.ic_menu_save);
|
||||
menu.add(0, MENU_CANCEL, 0, R.string.menu_discard_apn_change)
|
||||
.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_DELETE:
|
||||
deleteApn();
|
||||
return true;
|
||||
|
||||
case MENU_SAVE:
|
||||
if (validateAndSave(false)) {
|
||||
getActivity().finish();
|
||||
}
|
||||
return true;
|
||||
|
||||
case MENU_CANCEL:
|
||||
getActivity().finish();
|
||||
return true;
|
||||
|
||||
case android.R.id.home:
|
||||
getActivity().onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle icicle) {
|
||||
super.onSaveInstanceState(icicle);
|
||||
if (validateAndSave(true) && mCursor != null) {
|
||||
icicle.putInt(SAVED_POS, mCursor.getInt(ID_INDEX));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the key fields' validity and save if valid.
|
||||
* @param force save even if the fields are not valid, if the app is
|
||||
* being suspended
|
||||
* @return true if the data was saved
|
||||
*/
|
||||
private boolean validateAndSave(boolean force) {
|
||||
final String name = checkNotSet(mName.getText());
|
||||
final String mcc = checkNotSet(mMcc.getText());
|
||||
final String mnc = checkNotSet(mMnc.getText());
|
||||
|
||||
if (getErrorMsg() != null && !force) {
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putString(ERROR_MESSAGE_KEY, getErrorMsg());
|
||||
getActivity().showDialog(ERROR_DIALOG_ID, bundle);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make database changes not on the UI thread
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
ContentValues values = new ContentValues();
|
||||
|
||||
// Add a placeholder name "Untitled", if the user exits the screen without
|
||||
// adding a name but entered other information worth keeping.
|
||||
values.put(Telephony.Carriers.NAME, name.length() < 1 ?
|
||||
getResources().getString(R.string.untitled_apn) : name);
|
||||
values.put(Telephony.Carriers.MMSPROXY, checkNotSet(mMmsProxy.getText()));
|
||||
values.put(Telephony.Carriers.MMSPORT, checkNotSet(mMmsPort.getText()));
|
||||
values.put(Telephony.Carriers.MMSC, checkNotSet(mMmsc.getText()));
|
||||
|
||||
values.put(Telephony.Carriers.TYPE, BugleApnSettingsLoader.APN_TYPE_MMS);
|
||||
|
||||
values.put(Telephony.Carriers.MCC, mcc);
|
||||
values.put(Telephony.Carriers.MNC, mnc);
|
||||
|
||||
values.put(Telephony.Carriers.NUMERIC, mcc + mnc);
|
||||
|
||||
if (mCurMnc != null && mCurMcc != null) {
|
||||
if (mCurMnc.equals(mnc) && mCurMcc.equals(mcc)) {
|
||||
values.put(Telephony.Carriers.CURRENT, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mNewApn) {
|
||||
mDatabase.insert(ApnDatabase.APN_TABLE, null, values);
|
||||
} else {
|
||||
// update the APN
|
||||
String selection = Telephony.Carriers._ID + " =?";
|
||||
String[] selectionArgs = new String[]{ mCurrentId };
|
||||
int updated = mDatabase.update(ApnDatabase.APN_TABLE, values,
|
||||
selection, selectionArgs);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.execute((Void) null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void deleteApn() {
|
||||
// Make database changes not on the UI thread
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
// delete the APN
|
||||
String where = Telephony.Carriers._ID + " =?";
|
||||
String[] whereArgs = new String[]{ mCurrentId };
|
||||
|
||||
mDatabase.delete(ApnDatabase.APN_TABLE, where, whereArgs);
|
||||
return null;
|
||||
}
|
||||
}.execute((Void) null);
|
||||
|
||||
getActivity().finish();
|
||||
}
|
||||
|
||||
private String checkNull(String value) {
|
||||
if (value == null || value.length() == 0) {
|
||||
return sNotSet;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
Preference pref = findPreference(key);
|
||||
if (pref != null) {
|
||||
pref.setSummary(checkNull(sharedPreferences.getString(key, "")));
|
||||
}
|
||||
}
|
||||
|
||||
private String getErrorMsg() {
|
||||
String errorMsg = null;
|
||||
|
||||
String name = checkNotSet(mName.getText());
|
||||
String mcc = checkNotSet(mMcc.getText());
|
||||
String mnc = checkNotSet(mMnc.getText());
|
||||
|
||||
if (name.length() < 1) {
|
||||
errorMsg = getString(R.string.error_apn_name_empty);
|
||||
} else if (mcc.length() != 3) {
|
||||
errorMsg = getString(R.string.error_mcc_not3);
|
||||
} else if ((mnc.length() & 0xFFFE) != 2) {
|
||||
errorMsg = getString(R.string.error_mnc_not23);
|
||||
}
|
||||
|
||||
return errorMsg;
|
||||
}
|
||||
|
||||
private String checkNotSet(String value) {
|
||||
if (value == null || value.equals(sNotSet)) {
|
||||
return "";
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.ui.appsettings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.datamodel.data.ParticipantData;
|
||||
import com.android.messaging.ui.UIIntents;
|
||||
|
||||
/**
|
||||
* ApnPreference implements a pref, typically used as a list item, that has a title/summary on
|
||||
* the left and a radio button on the right.
|
||||
*
|
||||
*/
|
||||
public class ApnPreference extends Preference implements
|
||||
CompoundButton.OnCheckedChangeListener, OnClickListener {
|
||||
static final String TAG = "ApnPreference";
|
||||
|
||||
public ApnPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public ApnPreference(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.apnPreferenceStyle);
|
||||
}
|
||||
|
||||
public ApnPreference(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
private static String mSelectedKey = null;
|
||||
private static CompoundButton mCurrentChecked = null;
|
||||
private boolean mProtectFromCheckedChange = false;
|
||||
private boolean mSelectable = true;
|
||||
private int mSubId = ParticipantData.DEFAULT_SELF_SUB_ID;
|
||||
|
||||
@Override
|
||||
public View getView(View convertView, ViewGroup parent) {
|
||||
View view = super.getView(convertView, parent);
|
||||
|
||||
View widget = view.findViewById(R.id.apn_radiobutton);
|
||||
if ((widget != null) && widget instanceof RadioButton) {
|
||||
RadioButton rb = (RadioButton) widget;
|
||||
if (mSelectable) {
|
||||
rb.setOnCheckedChangeListener(this);
|
||||
|
||||
boolean isChecked = getKey().equals(mSelectedKey);
|
||||
if (isChecked) {
|
||||
mCurrentChecked = rb;
|
||||
mSelectedKey = getKey();
|
||||
}
|
||||
|
||||
mProtectFromCheckedChange = true;
|
||||
rb.setChecked(isChecked);
|
||||
mProtectFromCheckedChange = false;
|
||||
} else {
|
||||
rb.setVisibility(View.GONE);
|
||||
}
|
||||
rb.setContentDescription(getTitle());
|
||||
}
|
||||
|
||||
View textLayout = view.findViewById(R.id.text_layout);
|
||||
if ((textLayout != null) && textLayout instanceof RelativeLayout) {
|
||||
textLayout.setOnClickListener(this);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return getKey().equals(mSelectedKey);
|
||||
}
|
||||
|
||||
public void setChecked() {
|
||||
mSelectedKey = getKey();
|
||||
}
|
||||
|
||||
public void setSubId(final int subId) {
|
||||
mSubId = subId;
|
||||
}
|
||||
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
Log.i(TAG, "ID: " + getKey() + " :" + isChecked);
|
||||
if (mProtectFromCheckedChange) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isChecked) {
|
||||
if (mCurrentChecked != null) {
|
||||
mCurrentChecked.setChecked(false);
|
||||
}
|
||||
mCurrentChecked = buttonView;
|
||||
mSelectedKey = getKey();
|
||||
callChangeListener(mSelectedKey);
|
||||
} else {
|
||||
mCurrentChecked = null;
|
||||
mSelectedKey = null;
|
||||
}
|
||||
buttonView.setContentDescription(getTitle());
|
||||
}
|
||||
|
||||
public void onClick(android.view.View v) {
|
||||
if ((v != null) && (R.id.text_layout == v.getId())) {
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
context.startActivity(
|
||||
UIIntents.get().getApnEditorIntent(context, getKey(), mSubId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setSelectable(boolean selectable) {
|
||||
mSelectable = selectable;
|
||||
}
|
||||
|
||||
public boolean getSelectable() {
|
||||
return mSelectable;
|
||||
}
|
||||
}
|
||||
@@ -1,402 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS 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.messaging.ui.appsettings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.UserManager;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.provider.Telephony;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.NavUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.datamodel.data.ParticipantData;
|
||||
import com.android.messaging.sms.ApnDatabase;
|
||||
import com.android.messaging.sms.BugleApnSettingsLoader;
|
||||
import com.android.messaging.ui.BugleActionBarActivity;
|
||||
import com.android.messaging.ui.UIIntents;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
|
||||
public class ApnSettingsActivity extends BugleActionBarActivity {
|
||||
private static final int DIALOG_RESTORE_DEFAULTAPN = 1001;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
// Display the fragment as the main content.
|
||||
final ApnSettingsFragment fragment = new ApnSettingsFragment();
|
||||
fragment.setSubId(getIntent().getIntExtra(UIIntents.UI_INTENT_EXTRA_SUB_ID,
|
||||
ParticipantData.DEFAULT_SELF_SUB_ID));
|
||||
getFragmentManager().beginTransaction()
|
||||
.replace(android.R.id.content, fragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
NavUtils.navigateUpFromSameTask(this);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(int id) {
|
||||
if (id == DIALOG_RESTORE_DEFAULTAPN) {
|
||||
ProgressDialog dialog = new ProgressDialog(this);
|
||||
dialog.setMessage(getResources().getString(R.string.restore_default_apn));
|
||||
dialog.setCancelable(false);
|
||||
return dialog;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class ApnSettingsFragment extends PreferenceFragment implements
|
||||
Preference.OnPreferenceChangeListener {
|
||||
public static final String EXTRA_POSITION = "position";
|
||||
|
||||
public static final String APN_ID = "apn_id";
|
||||
|
||||
private static final String[] APN_PROJECTION = {
|
||||
Telephony.Carriers._ID, // 0
|
||||
Telephony.Carriers.NAME, // 1
|
||||
Telephony.Carriers.APN, // 2
|
||||
Telephony.Carriers.TYPE // 3
|
||||
};
|
||||
private static final int ID_INDEX = 0;
|
||||
private static final int NAME_INDEX = 1;
|
||||
private static final int APN_INDEX = 2;
|
||||
private static final int TYPES_INDEX = 3;
|
||||
|
||||
private static final int MENU_NEW = Menu.FIRST;
|
||||
private static final int MENU_RESTORE = Menu.FIRST + 1;
|
||||
|
||||
private static final int EVENT_RESTORE_DEFAULTAPN_START = 1;
|
||||
private static final int EVENT_RESTORE_DEFAULTAPN_COMPLETE = 2;
|
||||
|
||||
private static boolean mRestoreDefaultApnMode;
|
||||
|
||||
private RestoreApnUiHandler mRestoreApnUiHandler;
|
||||
private RestoreApnProcessHandler mRestoreApnProcessHandler;
|
||||
private HandlerThread mRestoreDefaultApnThread;
|
||||
|
||||
private String mSelectedKey;
|
||||
|
||||
private static final ContentValues sCurrentNullMap;
|
||||
private static final ContentValues sCurrentSetMap;
|
||||
|
||||
private UserManager mUm;
|
||||
|
||||
private boolean mUnavailable;
|
||||
private int mSubId;
|
||||
|
||||
static {
|
||||
sCurrentNullMap = new ContentValues(1);
|
||||
sCurrentNullMap.putNull(Telephony.Carriers.CURRENT);
|
||||
|
||||
sCurrentSetMap = new ContentValues(1);
|
||||
sCurrentSetMap.put(Telephony.Carriers.CURRENT, "2"); // 2 for user-selected APN,
|
||||
// 1 for Bugle-selected APN
|
||||
}
|
||||
|
||||
private SQLiteDatabase mDatabase;
|
||||
|
||||
public void setSubId(final int subId) {
|
||||
mSubId = subId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
mDatabase = ApnDatabase.getApnDatabase().getWritableDatabase();
|
||||
mUm = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
|
||||
if (!mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
final ListView lv = (ListView) getView().findViewById(android.R.id.list);
|
||||
TextView empty = (TextView) getView().findViewById(android.R.id.empty);
|
||||
if (empty != null) {
|
||||
empty.setText(R.string.apn_settings_not_available);
|
||||
lv.setEmptyView(empty);
|
||||
}
|
||||
|
||||
if (mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
|
||||
mUnavailable = true;
|
||||
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity()));
|
||||
return;
|
||||
}
|
||||
|
||||
addPreferencesFromResource(R.xml.apn_settings);
|
||||
|
||||
lv.setItemsCanFocus(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (mUnavailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mRestoreDefaultApnMode) {
|
||||
fillList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (mUnavailable) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
if (mRestoreDefaultApnThread != null) {
|
||||
mRestoreDefaultApnThread.quit();
|
||||
}
|
||||
}
|
||||
|
||||
private void fillList() {
|
||||
final String mccMnc = PhoneUtils.getMccMncString(PhoneUtils.get(mSubId).getMccMnc());
|
||||
|
||||
new AsyncTask<Void, Void, Cursor>() {
|
||||
@Override
|
||||
protected Cursor doInBackground(Void... params) {
|
||||
String selection = Telephony.Carriers.NUMERIC + " =?";
|
||||
String[] selectionArgs = new String[]{ mccMnc };
|
||||
final Cursor cursor = mDatabase.query(ApnDatabase.APN_TABLE, APN_PROJECTION,
|
||||
selection, selectionArgs, null, null, null, null);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Cursor cursor) {
|
||||
if (cursor != null) {
|
||||
try {
|
||||
PreferenceGroup apnList = (PreferenceGroup)
|
||||
findPreference(getString(R.string.apn_list_pref_key));
|
||||
apnList.removeAll();
|
||||
|
||||
mSelectedKey = BugleApnSettingsLoader.getFirstTryApn(mDatabase, mccMnc);
|
||||
while (cursor.moveToNext()) {
|
||||
String name = cursor.getString(NAME_INDEX);
|
||||
String apn = cursor.getString(APN_INDEX);
|
||||
String key = cursor.getString(ID_INDEX);
|
||||
String type = cursor.getString(TYPES_INDEX);
|
||||
|
||||
if (BugleApnSettingsLoader.isValidApnType(type,
|
||||
BugleApnSettingsLoader.APN_TYPE_MMS)) {
|
||||
ApnPreference pref = new ApnPreference(getActivity());
|
||||
pref.setKey(key);
|
||||
pref.setTitle(name);
|
||||
pref.setSummary(apn);
|
||||
pref.setPersistent(false);
|
||||
pref.setOnPreferenceChangeListener(ApnSettingsFragment.this);
|
||||
pref.setSelectable(true);
|
||||
|
||||
// Turn on the radio button for the currently selected APN. If
|
||||
// there is no selected APN, don't select an APN.
|
||||
if ((mSelectedKey != null && mSelectedKey.equals(key))) {
|
||||
pref.setChecked();
|
||||
}
|
||||
apnList.addPreference(pref);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}.execute((Void) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
if (!mUnavailable) {
|
||||
menu.add(0, MENU_NEW, 0,
|
||||
getResources().getString(R.string.menu_new_apn))
|
||||
.setIcon(R.drawable.ic_add_white)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
menu.add(0, MENU_RESTORE, 0,
|
||||
getResources().getString(R.string.menu_restore_default_apn))
|
||||
.setIcon(android.R.drawable.ic_menu_upload);
|
||||
}
|
||||
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_NEW:
|
||||
addNewApn();
|
||||
return true;
|
||||
|
||||
case MENU_RESTORE:
|
||||
restoreDefaultApn();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void addNewApn() {
|
||||
startActivity(UIIntents.get().getApnEditorIntent(getActivity(), null, mSubId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
|
||||
Preference preference) {
|
||||
startActivity(
|
||||
UIIntents.get().getApnEditorIntent(getActivity(), preference.getKey(), mSubId));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (newValue instanceof String) {
|
||||
setSelectedApnKey((String) newValue);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// current=2 means user selected APN
|
||||
private static final String UPDATE_SELECTION = Telephony.Carriers.CURRENT + " =?";
|
||||
private static final String[] UPDATE_SELECTION_ARGS = new String[] { "2" };
|
||||
private void setSelectedApnKey(final String key) {
|
||||
mSelectedKey = key;
|
||||
|
||||
// Make database changes not on the UI thread
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
// null out the previous "current=2" APN
|
||||
mDatabase.update(ApnDatabase.APN_TABLE, sCurrentNullMap,
|
||||
UPDATE_SELECTION, UPDATE_SELECTION_ARGS);
|
||||
|
||||
// set the new "current" APN (2)
|
||||
String selection = Telephony.Carriers._ID + " =?";
|
||||
String[] selectionArgs = new String[]{ key };
|
||||
|
||||
mDatabase.update(ApnDatabase.APN_TABLE, sCurrentSetMap,
|
||||
selection, selectionArgs);
|
||||
return null;
|
||||
}
|
||||
}.execute((Void) null);
|
||||
}
|
||||
|
||||
private boolean restoreDefaultApn() {
|
||||
getActivity().showDialog(DIALOG_RESTORE_DEFAULTAPN);
|
||||
mRestoreDefaultApnMode = true;
|
||||
|
||||
if (mRestoreApnUiHandler == null) {
|
||||
mRestoreApnUiHandler = new RestoreApnUiHandler();
|
||||
}
|
||||
|
||||
if (mRestoreApnProcessHandler == null ||
|
||||
mRestoreDefaultApnThread == null) {
|
||||
mRestoreDefaultApnThread = new HandlerThread(
|
||||
"Restore default APN Handler: Process Thread");
|
||||
mRestoreDefaultApnThread.start();
|
||||
mRestoreApnProcessHandler = new RestoreApnProcessHandler(
|
||||
mRestoreDefaultApnThread.getLooper(), mRestoreApnUiHandler);
|
||||
}
|
||||
|
||||
mRestoreApnProcessHandler.sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_START);
|
||||
return true;
|
||||
}
|
||||
|
||||
private class RestoreApnUiHandler extends Handler {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case EVENT_RESTORE_DEFAULTAPN_COMPLETE:
|
||||
fillList();
|
||||
getPreferenceScreen().setEnabled(true);
|
||||
mRestoreDefaultApnMode = false;
|
||||
final Activity activity = getActivity();
|
||||
activity.dismissDialog(DIALOG_RESTORE_DEFAULTAPN);
|
||||
Toast.makeText(activity, getResources().getString(
|
||||
R.string.restore_default_apn_completed), Toast.LENGTH_LONG)
|
||||
.show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class RestoreApnProcessHandler extends Handler {
|
||||
private final Handler mCachedRestoreApnUiHandler;
|
||||
|
||||
public RestoreApnProcessHandler(Looper looper, Handler restoreApnUiHandler) {
|
||||
super(looper);
|
||||
this.mCachedRestoreApnUiHandler = restoreApnUiHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case EVENT_RESTORE_DEFAULTAPN_START:
|
||||
ApnDatabase.forceBuildAndLoadApnTables();
|
||||
mCachedRestoreApnUiHandler.sendEmptyMessage(
|
||||
EVENT_RESTORE_DEFAULTAPN_COMPLETE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,6 @@ import com.android.messaging.ui.BugleActionBarActivity;
|
||||
import com.android.messaging.ui.LicenseActivity;
|
||||
import com.android.messaging.ui.UIIntents;
|
||||
import com.android.messaging.util.BuglePrefs;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
|
||||
public class ApplicationSettingsActivity extends BugleActionBarActivity {
|
||||
@@ -117,12 +116,6 @@ public class ApplicationSettingsActivity extends BugleActionBarActivity {
|
||||
(SwitchPreference) findPreference(mSwipeRightToDeleteConversationkey);
|
||||
mIsSmsPreferenceClicked = false;
|
||||
|
||||
if (!DebugUtils.isDebugEnabled()) {
|
||||
final Preference debugCategory = findPreference(getString(
|
||||
R.string.debug_pref_key));
|
||||
getPreferenceScreen().removePreference(debugCategory);
|
||||
}
|
||||
|
||||
final PreferenceScreen advancedScreen = (PreferenceScreen) findPreference(
|
||||
getString(R.string.advanced_pref_key));
|
||||
final boolean topLevel = getActivity().getIntent().getBooleanExtra(
|
||||
|
||||
@@ -138,23 +138,6 @@ public class PerSubscriptionSettingsActivity extends BugleActionBarActivity {
|
||||
advancedCategory.removePreference(deliveryReportsPref);
|
||||
}
|
||||
|
||||
// Access Point Names (APNs)
|
||||
final PreferenceScreen apnsScreen =
|
||||
(PreferenceScreen) findPreference(getString(R.string.sms_apns_key));
|
||||
|
||||
if (!MmsManager.shouldUseLegacyMms()
|
||||
|| (MmsUtils.useSystemApnTable() && !ApnDatabase.doesDatabaseExist())) {
|
||||
// 1) Remove the ability to edit the local APN prefs if it doesn't use legacy APIs.
|
||||
// 2) Don't remove the ability to edit the local APN prefs if this device lets us
|
||||
// access the system APN, but we can't find the MCC/MNC in the APN table and we
|
||||
// created the local APN table in case the MCC/MNC was in there. In other words,
|
||||
// if the local APN table exists, let the user edit it.
|
||||
advancedCategory.removePreference((Preference) apnsScreen);
|
||||
} else {
|
||||
apnsScreen.setIntent(UIIntents.get()
|
||||
.getApnSettingsIntent(getPreferenceScreen().getContext(), mSubId));
|
||||
}
|
||||
|
||||
// We want to disable preferences if we are not the default app, but we do all of the
|
||||
// above first so that the user sees the correct information on the screen
|
||||
if (!PhoneUtils.getDefault().isDefaultSmsApp()) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +18,6 @@ package com.android.messaging.ui.contact;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.MergeCursor;
|
||||
import androidx.core.util.Pair;
|
||||
import android.text.TextUtils;
|
||||
import android.text.util.Rfc822Token;
|
||||
@@ -35,8 +35,6 @@ import com.android.ex.chips.RecipientEntry;
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.ContactRecipientEntryUtils;
|
||||
import com.android.messaging.util.ContactUtil;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
@@ -116,40 +114,16 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
|
||||
@DoesNotRunOnMainThread
|
||||
private CursorResult getFilteredResultsCursor(final String searchText) {
|
||||
Assert.isNotMainThread();
|
||||
if (BugleGservices.get().getBoolean(
|
||||
BugleGservicesKeys.ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS,
|
||||
BugleGservicesKeys.ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS_DEFAULT)) {
|
||||
|
||||
final Cursor personalFilterPhonesCursor = ContactUtil
|
||||
.filterPhones(getContext(), searchText).performSynchronousQuery();
|
||||
final Cursor personalFilterEmailsCursor = ContactUtil
|
||||
.filterEmails(getContext(), searchText).performSynchronousQuery();
|
||||
final Cursor personalCursor = new MergeCursor(
|
||||
new Cursor[]{personalFilterEmailsCursor, personalFilterPhonesCursor});
|
||||
final CursorResult cursorResult =
|
||||
new CursorResult(personalCursor, false /* sorted */);
|
||||
// Including enterprise result starting from N.
|
||||
final Cursor enterpriseFilterPhonesCursor = ContactUtil.filterPhonesEnterprise(
|
||||
getContext(), searchText).performSynchronousQuery();
|
||||
final Cursor enterpriseFilterEmailsCursor = ContactUtil.filterEmailsEnterprise(
|
||||
getContext(), searchText).performSynchronousQuery();
|
||||
final Cursor enterpriseCursor = new MergeCursor(
|
||||
new Cursor[]{enterpriseFilterEmailsCursor,
|
||||
enterpriseFilterPhonesCursor});
|
||||
cursorResult.enterpriseCursor = enterpriseCursor;
|
||||
return cursorResult;
|
||||
} else {
|
||||
final Cursor personalFilterDestinationCursor = ContactUtil
|
||||
.filterDestination(getContext(), searchText).performSynchronousQuery();
|
||||
final CursorResult cursorResult = new CursorResult(personalFilterDestinationCursor,
|
||||
true);
|
||||
// Including enterprise result starting from N.
|
||||
final Cursor enterpriseFilterDestinationCursor = ContactUtil
|
||||
.filterDestinationEnterprise(getContext(), searchText)
|
||||
.performSynchronousQuery();
|
||||
cursorResult.enterpriseCursor = enterpriseFilterDestinationCursor;
|
||||
return cursorResult;
|
||||
}
|
||||
final Cursor personalFilterDestinationCursor = ContactUtil
|
||||
.filterDestination(getContext(), searchText).performSynchronousQuery();
|
||||
final CursorResult cursorResult = new CursorResult(personalFilterDestinationCursor,
|
||||
true);
|
||||
// Including enterprise result starting from N.
|
||||
final Cursor enterpriseFilterDestinationCursor = ContactUtil
|
||||
.filterDestinationEnterprise(getContext(), searchText)
|
||||
.performSynchronousQuery();
|
||||
cursorResult.enterpriseCursor = enterpriseFilterDestinationCursor;
|
||||
return cursorResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,9 +37,7 @@ import com.android.messaging.sms.MmsUtils;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
|
||||
import com.android.messaging.util.Dates;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
import com.android.messaging.util.SafeAsyncTask;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -52,22 +50,8 @@ public class MessageDetailsDialog {
|
||||
|
||||
public static void show(final Context context, final ConversationMessageData data,
|
||||
final ConversationParticipantsData participants, final ParticipantData self) {
|
||||
if (DebugUtils.isDebugEnabled()) {
|
||||
new SafeAsyncTask<Void, Void, String>() {
|
||||
@Override
|
||||
protected String doInBackgroundTimed(Void... params) {
|
||||
return getMessageDetails(context, data, participants, self);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String messageDetails) {
|
||||
showDialog(context, messageDetails);
|
||||
}
|
||||
}.executeOnThreadPool(null, null, null);
|
||||
} else {
|
||||
String messageDetails = getMessageDetails(context, data, participants, self);
|
||||
showDialog(context, messageDetails);
|
||||
}
|
||||
String messageDetails = getMessageDetails(context, data, participants, self);
|
||||
showDialog(context, messageDetails);
|
||||
}
|
||||
|
||||
private static String getMessageDetails(final Context context,
|
||||
@@ -140,10 +124,6 @@ public class MessageDetailsDialog {
|
||||
|
||||
appendSimInfo(res, self, details);
|
||||
|
||||
if (DebugUtils.isDebugEnabled()) {
|
||||
appendDebugInfo(details, data);
|
||||
}
|
||||
|
||||
return details.toString();
|
||||
}
|
||||
|
||||
@@ -206,10 +186,6 @@ public class MessageDetailsDialog {
|
||||
|
||||
appendSimInfo(res, self, details);
|
||||
|
||||
if (DebugUtils.isDebugEnabled()) {
|
||||
appendDebugInfo(details, data);
|
||||
}
|
||||
|
||||
return details.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,9 +40,6 @@ import com.android.messaging.ui.UIIntents;
|
||||
import com.android.messaging.ui.contact.AddContactsConfirmationDialog;
|
||||
import com.android.messaging.ui.conversationlist.ConversationListFragment.ConversationListFragmentHost;
|
||||
import com.android.messaging.ui.conversationlist.MultiSelectActionModeCallback.SelectedConversation;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
import com.android.messaging.util.Trace;
|
||||
import com.android.messaging.util.UiUtils;
|
||||
@@ -268,10 +265,6 @@ public abstract class AbstractConversationListActivity extends BugleActionBarAc
|
||||
conversationId);
|
||||
}
|
||||
|
||||
public void onActionBarDebug() {
|
||||
DebugUtils.showDebugOptions(this);
|
||||
}
|
||||
|
||||
private static class UpdateDestinationBlockedActionSnackBar
|
||||
implements UpdateDestinationBlockedAction.UpdateDestinationBlockedActionListener {
|
||||
private final Context mContext;
|
||||
|
||||
@@ -21,11 +21,9 @@ import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
|
||||
public class ArchivedConversationListActivity extends AbstractConversationListActivity {
|
||||
|
||||
@@ -60,25 +58,8 @@ public class ArchivedConversationListActivity extends AbstractConversationListAc
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
if (super.onCreateOptionsMenu(menu)) {
|
||||
return true;
|
||||
}
|
||||
getMenuInflater().inflate(R.menu.archived_conversation_list_menu, menu);
|
||||
final MenuItem item = menu.findItem(R.id.action_debug_options);
|
||||
if (item != null) {
|
||||
final boolean enableDebugItems = DebugUtils.isDebugEnabled();
|
||||
item.setVisible(enableDebugItems).setEnabled(enableDebugItems);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem menuItem) {
|
||||
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
||||
switch(menuItem.getItemId()) {
|
||||
case R.id.action_debug_options:
|
||||
onActionBarDebug();
|
||||
return true;
|
||||
case android.R.id.home:
|
||||
onActionBarHome();
|
||||
return true;
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.view.MenuItem;
|
||||
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.ui.UIIntents;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
import com.android.messaging.util.Trace;
|
||||
|
||||
public class ConversationListActivity extends AbstractConversationListActivity {
|
||||
@@ -77,11 +76,6 @@ public class ConversationListActivity extends AbstractConversationListActivity {
|
||||
return true;
|
||||
}
|
||||
getMenuInflater().inflate(R.menu.conversation_list_fragment_menu, menu);
|
||||
final MenuItem item = menu.findItem(R.id.action_debug_options);
|
||||
if (item != null) {
|
||||
final boolean enableDebugItems = DebugUtils.isDebugEnabled();
|
||||
item.setVisible(enableDebugItems).setEnabled(enableDebugItems);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -94,9 +88,6 @@ public class ConversationListActivity extends AbstractConversationListActivity {
|
||||
case R.id.action_settings:
|
||||
onActionBarSettings();
|
||||
return true;
|
||||
case R.id.action_debug_options:
|
||||
onActionBarDebug();
|
||||
return true;
|
||||
case R.id.action_show_archived:
|
||||
onActionBarArchived();
|
||||
return true;
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.ui.debug;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.ui.BaseBugleActivity;
|
||||
|
||||
/**
|
||||
* Show list of all MmsConfig key/value pairs and allow editing.
|
||||
*/
|
||||
public class DebugMmsConfigActivity extends BaseBugleActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.debug_mmsconfig_activity);
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.ui.debug;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.sms.MmsConfig;
|
||||
import com.android.messaging.ui.debug.DebugMmsConfigItemView.MmsConfigItemListener;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Show list of all MmsConfig key/value pairs and allow editing.
|
||||
*/
|
||||
public class DebugMmsConfigFragment extends Fragment {
|
||||
@Override
|
||||
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
final View fragmentView = inflater.inflate(R.layout.mms_config_debug_fragment, container,
|
||||
false);
|
||||
final ListView listView = (ListView) fragmentView.findViewById(android.R.id.list);
|
||||
final Spinner spinner = (Spinner) fragmentView.findViewById(R.id.sim_selector);
|
||||
final Integer[] subIdArray = getActiveSubIds();
|
||||
ArrayAdapter<Integer> spinnerAdapter = new ArrayAdapter<Integer>(getActivity(),
|
||||
android.R.layout.simple_spinner_item, subIdArray);
|
||||
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(spinnerAdapter);
|
||||
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
listView.setAdapter(new MmsConfigAdapter(getActivity(), subIdArray[position]));
|
||||
|
||||
final int[] mccmnc = PhoneUtils.get(subIdArray[position]).getMccMnc();
|
||||
// Set the title with the mcc/mnc
|
||||
final TextView title = (TextView) fragmentView.findViewById(R.id.sim_title);
|
||||
title.setText("(" + mccmnc[0] + "/" + mccmnc[1] + ") " +
|
||||
getActivity().getString(R.string.debug_sub_id_spinner_text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
}
|
||||
});
|
||||
|
||||
return fragmentView;
|
||||
}
|
||||
|
||||
public static Integer[] getActiveSubIds() {
|
||||
final List<SubscriptionInfo> subRecords =
|
||||
PhoneUtils.getDefault().getActiveSubscriptionInfoList();
|
||||
if (subRecords == null) {
|
||||
return new Integer[0];
|
||||
}
|
||||
final Integer[] retArray = new Integer[subRecords.size()];
|
||||
for (int i = 0; i < subRecords.size(); i++) {
|
||||
retArray[i] = subRecords.get(i).getSubscriptionId();
|
||||
}
|
||||
return retArray;
|
||||
}
|
||||
|
||||
private class MmsConfigAdapter extends BaseAdapter implements
|
||||
DebugMmsConfigItemView.MmsConfigItemListener {
|
||||
private final LayoutInflater mInflater;
|
||||
private final List<String> mKeys;
|
||||
private final MmsConfig mMmsConfig;
|
||||
|
||||
public MmsConfigAdapter(Context context, int subId) {
|
||||
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mMmsConfig = MmsConfig.get(subId);
|
||||
mKeys = new ArrayList<>(mMmsConfig.keySet());
|
||||
Iterator<String> it = mKeys.iterator();
|
||||
while (it.hasNext()) {
|
||||
// Remove a config if the MmsConfig.sKeyTypeMap doesn't have it.
|
||||
if (MmsConfig.getKeyType(it.next()) == null) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
Collections.sort(mKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, final View convertView, final ViewGroup parent) {
|
||||
final DebugMmsConfigItemView view;
|
||||
if (convertView != null && convertView instanceof DebugMmsConfigItemView) {
|
||||
view = (DebugMmsConfigItemView) convertView;
|
||||
} else {
|
||||
view = (DebugMmsConfigItemView) mInflater.inflate(
|
||||
R.layout.debug_mmsconfig_item_view, parent, false);
|
||||
}
|
||||
final String key = mKeys.get(position);
|
||||
view.bind(key,
|
||||
MmsConfig.getKeyType(key),
|
||||
String.valueOf(mMmsConfig.getValue(key)),
|
||||
this);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValueChanged(String key, String keyType, String value) {
|
||||
mMmsConfig.update(keyType, key, value);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mKeys.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return mKeys.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS 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.messaging.ui.debug;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.text.InputType;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.sms.MmsConfig;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
|
||||
public class DebugMmsConfigItemView extends LinearLayout implements OnClickListener,
|
||||
OnCheckedChangeListener, DialogInterface.OnClickListener {
|
||||
|
||||
public interface MmsConfigItemListener {
|
||||
void onValueChanged(String key, String keyType, String value);
|
||||
}
|
||||
|
||||
private TextView mTitle;
|
||||
private TextView mTextValue;
|
||||
private Switch mSwitch;
|
||||
private String mKey;
|
||||
private String mKeyType;
|
||||
private MmsConfigItemListener mListener;
|
||||
private EditText mEditText;
|
||||
|
||||
public DebugMmsConfigItemView(Context context, AttributeSet attributeSet) {
|
||||
super(context, attributeSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate () {
|
||||
mTitle = (TextView) findViewById(R.id.title);
|
||||
mTextValue = (TextView) findViewById(R.id.text_value);
|
||||
mSwitch = (Switch) findViewById(R.id.switch_button);
|
||||
setOnClickListener(this);
|
||||
mSwitch.setOnCheckedChangeListener(this);
|
||||
}
|
||||
|
||||
public void bind(final String key, final String keyType, final String value,
|
||||
final MmsConfigItemListener listener) {
|
||||
mListener = listener;
|
||||
mKey = key;
|
||||
mKeyType = keyType;
|
||||
mTitle.setText(key);
|
||||
|
||||
switch (keyType) {
|
||||
case MmsConfig.KEY_TYPE_BOOL:
|
||||
mSwitch.setVisibility(View.VISIBLE);
|
||||
mTextValue.setVisibility(View.GONE);
|
||||
mSwitch.setChecked(Boolean.valueOf(value));
|
||||
break;
|
||||
case MmsConfig.KEY_TYPE_STRING:
|
||||
case MmsConfig.KEY_TYPE_INT:
|
||||
mTextValue.setVisibility(View.VISIBLE);
|
||||
mSwitch.setVisibility(View.GONE);
|
||||
mTextValue.setText(value);
|
||||
break;
|
||||
default:
|
||||
mTextValue.setVisibility(View.GONE);
|
||||
mSwitch.setVisibility(View.GONE);
|
||||
LogUtil.e(LogUtil.BUGLE_TAG, "Unexpected keytype: " + keyType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
mListener.onValueChanged(mKey, mKeyType, String.valueOf(isChecked));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (MmsConfig.KEY_TYPE_BOOL.equals(mKeyType)) {
|
||||
return;
|
||||
}
|
||||
final Context context = getContext();
|
||||
mEditText = new EditText(context);
|
||||
mEditText.setText(mTextValue.getText());
|
||||
mEditText.setFocusable(true);
|
||||
if (MmsConfig.KEY_TYPE_INT.equals(mKeyType)) {
|
||||
mEditText.setInputType(InputType.TYPE_CLASS_PHONE);
|
||||
} else {
|
||||
mEditText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
}
|
||||
final AlertDialog dialog = new AlertDialog.Builder(context)
|
||||
.setTitle(mKey)
|
||||
.setView(mEditText)
|
||||
.setPositiveButton(android.R.string.ok, this)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create();
|
||||
dialog.setOnShowListener(dialog1 -> {
|
||||
mEditText.requestFocus();
|
||||
mEditText.selectAll();
|
||||
((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE))
|
||||
.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
mListener.onValueChanged(mKey, mKeyType, mEditText.getText().toString());
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS 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.messaging.ui.debug;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.telephony.SmsMessage;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.datamodel.action.ReceiveMmsMessageAction;
|
||||
import com.android.messaging.datamodel.data.ParticipantData;
|
||||
import com.android.messaging.receiver.SmsReceiver;
|
||||
import com.android.messaging.sms.MmsUtils;
|
||||
import com.android.messaging.util.DebugUtils;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
|
||||
/**
|
||||
* Class that displays UI for choosing SMS/MMS dump files for debugging
|
||||
*/
|
||||
public class DebugSmsMmsFromDumpFileDialogFragment extends DialogFragment {
|
||||
public static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
|
||||
public static final String KEY_DUMP_FILES = "dump_files";
|
||||
public static final String KEY_ACTION = "action";
|
||||
|
||||
public static final String ACTION_LOAD = "load";
|
||||
public static final String ACTION_EMAIL = "email";
|
||||
|
||||
private String[] mDumpFiles;
|
||||
private String mAction;
|
||||
|
||||
public static DebugSmsMmsFromDumpFileDialogFragment newInstance(final String[] dumpFiles,
|
||||
final String action) {
|
||||
final DebugSmsMmsFromDumpFileDialogFragment frag =
|
||||
new DebugSmsMmsFromDumpFileDialogFragment();
|
||||
final Bundle args = new Bundle();
|
||||
args.putSerializable(KEY_DUMP_FILES, dumpFiles);
|
||||
args.putString(KEY_ACTION, action);
|
||||
frag.setArguments(args);
|
||||
return frag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Bundle args = getArguments();
|
||||
mDumpFiles = (String[]) args.getSerializable(KEY_DUMP_FILES);
|
||||
mAction = args.getString(KEY_ACTION);
|
||||
|
||||
final LayoutInflater inflater = getActivity().getLayoutInflater();
|
||||
final View layout = inflater.inflate(
|
||||
R.layout.debug_sms_mms_from_dump_file_dialog, null/*root*/);
|
||||
final ListView list = (ListView) layout.findViewById(R.id.dump_file_list);
|
||||
list.setAdapter(new DumpFileListAdapter(getActivity(), mDumpFiles));
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
final Resources resources = getResources();
|
||||
if (ACTION_LOAD.equals(mAction)) {
|
||||
builder.setTitle(resources.getString(
|
||||
R.string.load_sms_mms_from_dump_file_dialog_title));
|
||||
} else if (ACTION_EMAIL.equals(mAction)) {
|
||||
builder.setTitle(resources.getString(
|
||||
R.string.email_sms_mms_from_dump_file_dialog_title));
|
||||
}
|
||||
builder.setView(layout);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private class DumpFileListAdapter extends ArrayAdapter<String> {
|
||||
public DumpFileListAdapter(final Context context, final String[] dumpFiles) {
|
||||
super(context, R.layout.sms_mms_dump_file_list_item, dumpFiles);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(final int position, final View view, @NonNull final ViewGroup parent) {
|
||||
TextView actionItemView;
|
||||
if (view == null || !(view instanceof TextView)) {
|
||||
final LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
actionItemView = (TextView) inflater.inflate(
|
||||
R.layout.sms_mms_dump_file_list_item, parent, false);
|
||||
} else {
|
||||
actionItemView = (TextView) view;
|
||||
}
|
||||
|
||||
final String file = getItem(position);
|
||||
actionItemView.setText(file);
|
||||
actionItemView.setOnClickListener(view1 -> {
|
||||
dismiss();
|
||||
if (ACTION_LOAD.equals(mAction)) {
|
||||
receiveFromDumpFile(file);
|
||||
} else if (ACTION_EMAIL.equals(mAction)) {
|
||||
emailDumpFile(file);
|
||||
}
|
||||
});
|
||||
return actionItemView;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load MMS/SMS from the dump file
|
||||
*/
|
||||
private void receiveFromDumpFile(final String dumpFileName) {
|
||||
if (dumpFileName.startsWith(MmsUtils.SMS_DUMP_PREFIX)) {
|
||||
final SmsMessage[] messages = DebugUtils.retreiveSmsFromDumpFile(dumpFileName);
|
||||
if (messages != null) {
|
||||
SmsReceiver.deliverSmsMessages(getActivity(), ParticipantData.DEFAULT_SELF_SUB_ID,
|
||||
0, messages);
|
||||
} else {
|
||||
LogUtil.e(LogUtil.BUGLE_TAG,
|
||||
"receiveFromDumpFile: invalid sms dump file " + dumpFileName);
|
||||
}
|
||||
} else if (dumpFileName.startsWith(MmsUtils.MMS_DUMP_PREFIX)) {
|
||||
final byte[] data = MmsUtils.createDebugNotificationInd(dumpFileName);
|
||||
if (data != null) {
|
||||
final ReceiveMmsMessageAction action = new ReceiveMmsMessageAction(
|
||||
ParticipantData.DEFAULT_SELF_SUB_ID, data);
|
||||
action.start();
|
||||
} else {
|
||||
LogUtil.e(LogUtil.BUGLE_TAG,
|
||||
"receiveFromDumpFile: invalid mms dump file " + dumpFileName);
|
||||
}
|
||||
} else {
|
||||
LogUtil.e(LogUtil.BUGLE_TAG,
|
||||
"receiveFromDumpFile: invalid dump file name " + dumpFileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch email app to send the dump file
|
||||
*/
|
||||
private void emailDumpFile(final String file) {
|
||||
final Resources resources = getResources();
|
||||
final String fileLocation = "file://"
|
||||
+ Environment.getExternalStorageDirectory() + "/" + file;
|
||||
final Intent sharingIntent = new Intent(Intent.ACTION_SEND);
|
||||
sharingIntent.setType(APPLICATION_OCTET_STREAM);
|
||||
sharingIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(fileLocation));
|
||||
sharingIntent.putExtra(Intent.EXTRA_SUBJECT,
|
||||
resources.getString(R.string.email_sms_mms_dump_file_subject));
|
||||
getActivity().startActivity(Intent.createChooser(sharingIntent,
|
||||
resources.getString(R.string.email_sms_mms_dump_file_chooser_title)));
|
||||
}
|
||||
}
|
||||
@@ -45,8 +45,6 @@ import com.android.messaging.sms.MmsConfig;
|
||||
import com.android.messaging.ui.mediapicker.camerafocus.FocusOverlayManager;
|
||||
import com.android.messaging.ui.mediapicker.camerafocus.RenderOverlay;
|
||||
import com.android.messaging.util.Assert;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
import com.android.messaging.util.OsUtil;
|
||||
import com.android.messaging.util.UiUtils;
|
||||
@@ -975,9 +973,7 @@ class CameraManager implements FocusOverlayManager.Listener {
|
||||
screenWidth *= scaleFactor;
|
||||
screenHeight *= scaleFactor;
|
||||
|
||||
final float aspectRatio = BugleGservices.get().getFloat(
|
||||
BugleGservicesKeys.CAMERA_ASPECT_RATIO,
|
||||
screenWidth / (float) screenHeight);
|
||||
final float aspectRatio = screenWidth / (float) screenHeight;
|
||||
final List<Camera.Size> sizes = new ArrayList<Camera.Size>(
|
||||
mCamera.getParameters().getSupportedPictureSizes());
|
||||
final int maxPixels = maxWidth * maxHeight;
|
||||
|
||||
@@ -40,27 +40,12 @@ public final class Assert {
|
||||
sShouldCrash = sIsEngBuild = true;
|
||||
}
|
||||
|
||||
private static void refreshGservices(final BugleGservices gservices) {
|
||||
sShouldCrash = sIsEngBuild;
|
||||
if (!sShouldCrash) {
|
||||
sShouldCrash = gservices.getBoolean(
|
||||
BugleGservicesKeys.ASSERTS_FATAL,
|
||||
BugleGservicesKeys.ASSERTS_FATAL_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
// Static initializer block to find out if we're running an eng or
|
||||
// release build.
|
||||
static {
|
||||
setIfEngBuild();
|
||||
}
|
||||
|
||||
// This is called from FactoryImpl once the Gservices class is initialized.
|
||||
public static void initializeGservices (final BugleGservices gservices) {
|
||||
gservices.registerForChanges(() -> refreshGservices(gservices));
|
||||
refreshGservices(gservices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Halt execution if this is not an eng build.
|
||||
* <p>Intended for use in code paths that should be run only for tests and never on
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.util;
|
||||
|
||||
import com.android.messaging.Factory;
|
||||
|
||||
/**
|
||||
* A thin wrapper for getting GServices value. During constructor time a one time background thread
|
||||
* will cache all GServices key with the prefix of "bugle_". All get calls will wait for Gservices
|
||||
* to finish caching the first time. In practice, the background thread will finish before any get
|
||||
* request.
|
||||
*/
|
||||
public abstract class BugleGservices {
|
||||
static final String BUGLE_GSERVICES_PREFIX = "bugle_";
|
||||
|
||||
public static BugleGservices get() {
|
||||
return Factory.get().getBugleGservices();
|
||||
}
|
||||
|
||||
public abstract void registerForChanges(final Runnable r);
|
||||
|
||||
/**
|
||||
* @param key The key to look up in GServices
|
||||
* @param defaultValue The default value if value in GServices is null or if
|
||||
* NumberFormatException is caught.
|
||||
* @return The corresponding value, or the default value.
|
||||
*/
|
||||
public abstract long getLong(final String key, final long defaultValue);
|
||||
|
||||
/**
|
||||
* @param key The key to look up in GServices
|
||||
* @param defaultValue The default value if value in GServices is null or if
|
||||
* NumberFormatException is caught.
|
||||
* @return The corresponding value, or the default value.
|
||||
*/
|
||||
public abstract int getInt(final String key, final int defaultValue);
|
||||
|
||||
/**
|
||||
* @param key The key to look up in GServices
|
||||
* @param defaultValue The default value if value in GServices is null.
|
||||
* @return The corresponding value, or the default value.
|
||||
*/
|
||||
public abstract boolean getBoolean(final String key, final boolean defaultValue);
|
||||
|
||||
/**
|
||||
* @param key The key to look up in GServices
|
||||
* @param defaultValue The default value if value in GServices is null.
|
||||
* @return The corresponding value, or the default value.
|
||||
*/
|
||||
public abstract String getString(final String key, final String defaultValue);
|
||||
|
||||
/**
|
||||
* @param key The key to look up in GServices
|
||||
* @param defaultValue The default value if value in GServices is null.
|
||||
* @return The corresponding value, or the default value.
|
||||
*/
|
||||
public abstract float getFloat(final String key, final float defaultValue);
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* A thin wrapper for getting GServices value.
|
||||
*/
|
||||
public class BugleGservicesImpl extends BugleGservices {
|
||||
public BugleGservicesImpl(final Context context) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerForChanges(final Runnable r) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the key has the expected prefix.
|
||||
*/
|
||||
private void assertKeyAndWaitForGservices(final String key) {
|
||||
Assert.isTrue(key.startsWith(BUGLE_GSERVICES_PREFIX));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(final String key, final long defaultValue) {
|
||||
assertKeyAndWaitForGservices(key);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(final String key, final int defaultValue) {
|
||||
assertKeyAndWaitForGservices(key);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(final String key, final boolean defaultValue) {
|
||||
assertKeyAndWaitForGservices(key);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(final String key, final String defaultValue) {
|
||||
assertKeyAndWaitForGservices(key);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(final String key, final float defaultValue) {
|
||||
assertKeyAndWaitForGservices(key);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
@@ -24,49 +24,29 @@ package com.android.messaging.util;
|
||||
public final class BugleGservicesKeys {
|
||||
private BugleGservicesKeys() {} // do not instantiate
|
||||
|
||||
/**
|
||||
* Whether to enable extra debugging features on the client. Default is
|
||||
* {@value #ENABLE_DEBUGGING_FEATURES_DEFAULT}.
|
||||
*/
|
||||
public static final String ENABLE_DEBUGGING_FEATURES
|
||||
= "bugle_debugging";
|
||||
public static final boolean ENABLE_DEBUGGING_FEATURES_DEFAULT
|
||||
= false;
|
||||
|
||||
/**
|
||||
* Whether to enable saving extra logs. Default is {@value #ENABLE_LOG_SAVER_DEFAULT}.
|
||||
*/
|
||||
public static final String ENABLE_LOG_SAVER = "bugle_logsaver";
|
||||
public static final boolean ENABLE_LOG_SAVER_DEFAULT = false;
|
||||
|
||||
/**
|
||||
* Time in milliseconds of initial (attempt 1) resend backoff for failing messages
|
||||
*/
|
||||
public static final String INITIAL_MESSAGE_RESEND_DELAY_MS = "bugle_resend_delay_in_millis";
|
||||
public static final long INITIAL_MESSAGE_RESEND_DELAY_MS_DEFAULT = 5 * 1000L;
|
||||
|
||||
/**
|
||||
* Time in milliseconds of max resend backoff for failing messages
|
||||
*/
|
||||
public static final String MAX_MESSAGE_RESEND_DELAY_MS = "bugle_max_resend_delay_in_millis";
|
||||
public static final long MAX_MESSAGE_RESEND_DELAY_MS_DEFAULT = 2 * 60 * 60 * 1000L;
|
||||
|
||||
/**
|
||||
* Time in milliseconds of resend window for unsent messages
|
||||
*/
|
||||
public static final String MESSAGE_RESEND_TIMEOUT_MS = "bugle_resend_timeout_in_millis";
|
||||
public static final long MESSAGE_RESEND_TIMEOUT_MS_DEFAULT = 20 * 60 * 1000L;
|
||||
|
||||
/**
|
||||
* Time in milliseconds of download window for new mms notifications
|
||||
*/
|
||||
public static final String MESSAGE_DOWNLOAD_TIMEOUT_MS = "bugle_download_timeout_in_millis";
|
||||
public static final long MESSAGE_DOWNLOAD_TIMEOUT_MS_DEFAULT = 20 * 60 * 1000L;
|
||||
|
||||
/**
|
||||
* Time in milliseconds for SMS send timeout
|
||||
*/
|
||||
public static final String SMS_SEND_TIMEOUT_IN_MILLIS = "bugle_sms_send_timeout";
|
||||
public static final long SMS_SEND_TIMEOUT_IN_MILLIS_DEFAULT = 5 * 60 * 1000L;
|
||||
|
||||
/**
|
||||
@@ -87,17 +67,9 @@ public final class BugleGservicesKeys {
|
||||
* whatever reasons. Keeping this low ensures responsiveness of the application.
|
||||
* 4. The limit on number of total messages to scan in one batch.
|
||||
*/
|
||||
public static final String SMS_SYNC_BATCH_SIZE_MIN =
|
||||
"bugle_sms_sync_batch_size_min";
|
||||
public static final int SMS_SYNC_BATCH_SIZE_MIN_DEFAULT = 80;
|
||||
public static final String SMS_SYNC_BATCH_SIZE_MAX =
|
||||
"bugle_sms_sync_batch_size_max";
|
||||
public static final int SMS_SYNC_BATCH_SIZE_MAX_DEFAULT = 1000;
|
||||
public static final String SMS_SYNC_BATCH_TIME_LIMIT_MILLIS =
|
||||
"bugle_sms_sync_batch_time_limit";
|
||||
public static final long SMS_SYNC_BATCH_TIME_LIMIT_MILLIS_DEFAULT = 400;
|
||||
public static final String SMS_SYNC_BATCH_MAX_MESSAGES_TO_SCAN =
|
||||
"bugle_sms_sync_batch_max_messages_to_scan";
|
||||
public static final int SMS_SYNC_BATCH_MAX_MESSAGES_TO_SCAN_DEFAULT =
|
||||
SMS_SYNC_BATCH_SIZE_MAX_DEFAULT * 4;
|
||||
|
||||
@@ -108,18 +80,13 @@ public final class BugleGservicesKeys {
|
||||
* when bringing in changes made outside the application. It also represents a buffer
|
||||
* to ensure that sync doesn't trigger based on changes made within the application.
|
||||
*/
|
||||
public static final String SMS_SYNC_BACKOFF_TIME_MILLIS =
|
||||
"bugle_sms_sync_backoff_time";
|
||||
public static final long SMS_SYNC_BACKOFF_TIME_MILLIS_DEFAULT = 5000L;
|
||||
|
||||
/**
|
||||
* Just in case if we fall into a loop of full sync -> still not synchronized -> full sync ...
|
||||
* This forces a backoff time so that we at most do full sync once a while (an hour by default)
|
||||
*/
|
||||
public static final String SMS_FULL_SYNC_BACKOFF_TIME_MILLIS =
|
||||
"bugle_sms_full_sync_backoff_time";
|
||||
public static final long SMS_FULL_SYNC_BACKOFF_TIME_MILLIS_DEFAULT = 60 * 60 * 1000;
|
||||
|
||||
/**
|
||||
* MMS UA profile url.
|
||||
*
|
||||
@@ -127,66 +94,30 @@ public final class BugleGservicesKeys {
|
||||
* latest and greatest phones. However, if we're on KitKat or below we can't get the phone's
|
||||
* UA profile and thus we need to send them the default url.
|
||||
*/
|
||||
public static final String MMS_UA_PROFILE_URL =
|
||||
"bugle_mms_uaprofurl";
|
||||
public static final String MMS_UA_PROFILE_URL_DEFAULT =
|
||||
"http://www.gstatic.com/android/sms/mms_ua_profile.xml";
|
||||
|
||||
/**
|
||||
* MMS apn mmsc
|
||||
*/
|
||||
public static final String MMS_MMSC =
|
||||
"bugle_mms_mmsc";
|
||||
|
||||
/**
|
||||
* MMS apn proxy ip address
|
||||
*/
|
||||
public static final String MMS_PROXY_ADDRESS =
|
||||
"bugle_mms_proxy_address";
|
||||
|
||||
/**
|
||||
* MMS apn proxy port
|
||||
*/
|
||||
public static final String MMS_PROXY_PORT =
|
||||
"bugle_mms_proxy_port";
|
||||
|
||||
/**
|
||||
* List of known SMS system messages that we will ignore (no deliver, no abort) so that the
|
||||
* user doesn't see them and the appropriate app is able to handle them. We are delivering
|
||||
* these as a \n delimited list of patterns, however we should eventually move to storing
|
||||
* them with the per-carrier mms config xml file.
|
||||
*/
|
||||
public static final String SMS_IGNORE_MESSAGE_REGEX =
|
||||
"bugle_sms_ignore_message_regex";
|
||||
public static final String SMS_IGNORE_MESSAGE_REGEX_DEFAULT = "";
|
||||
|
||||
/**
|
||||
* When receiving or importing an mms, limit the length of text to this limit. Huge blocks
|
||||
* of text can cause the app to hang/ANR/or crash in native text code..
|
||||
*/
|
||||
public static final String MMS_TEXT_LIMIT = "bugle_mms_text_limit";
|
||||
public static final int MMS_TEXT_LIMIT_DEFAULT = 2000;
|
||||
|
||||
/**
|
||||
* Max number of attachments the user may add to a single message.
|
||||
*/
|
||||
public static final String MMS_ATTACHMENT_LIMIT = "bugle_mms_attachment_limit";
|
||||
public static final int MMS_ATTACHMENT_LIMIT_DEFAULT = 10;
|
||||
|
||||
/**
|
||||
* The max number of messages to show in a single conversation notification. We always show
|
||||
* the most recent message. If this value is >1, we may also include prior messages as well.
|
||||
*/
|
||||
public static final String MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION =
|
||||
"bugle_max_messages_in_conversation_notification";
|
||||
public static final int MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_DEFAULT = 7;
|
||||
|
||||
/**
|
||||
* Time (in seconds) between notification ringing for incoming messages of the same
|
||||
* conversation. We won't ding more often than this value for messages coming in at a high rate.
|
||||
*/
|
||||
public static final String NOTIFICATION_TIME_BETWEEN_RINGS_SECONDS
|
||||
= "bugle_notification_time_between_rings_seconds";
|
||||
public static final int NOTIFICATION_TIME_BETWEEN_RINGS_SECONDS_DEFAULT = 10;
|
||||
|
||||
/**
|
||||
@@ -195,91 +126,11 @@ public final class BugleGservicesKeys {
|
||||
* less screen real estate, so we may want to optimize for that case. Note that if a wearable
|
||||
* is paired, this value will apply to notifications as shown both on the watch and the phone.
|
||||
*/
|
||||
public static final String MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_WITH_WEARABLE =
|
||||
"bugle_max_messages_in_conversation_notification_with_wearable";
|
||||
public static final int MAX_MESSAGES_IN_CONVERSATION_NOTIFICATION_WITH_WEARABLE_DEFAULT = 1;
|
||||
|
||||
/**
|
||||
* Regular expression to match against query. If it matches then display
|
||||
* the query plan for this query.
|
||||
*/
|
||||
public static final String EXPLAIN_QUERY_PLAN_REGEXP = "bugle_query_plan_regexp";
|
||||
|
||||
/**
|
||||
* Whether asserts are fatal on user/userdebug builds.
|
||||
* Default is {@value #ASSERTS_FATAL_DEFAULT}.
|
||||
*/
|
||||
public static final String ASSERTS_FATAL = "bugle_asserts_fatal";
|
||||
public static final boolean ASSERTS_FATAL_DEFAULT = false;
|
||||
|
||||
/**
|
||||
* Whether to use API for sending/downloading MMS (if present, true for L).
|
||||
* Default is {@value #USE_MMS_API_IF_PRESENT_DEFAULT}.
|
||||
*/
|
||||
public static final String USE_MMS_API_IF_PRESENT = "bugle_use_mms_api";
|
||||
public static final boolean USE_MMS_API_IF_PRESENT_DEFAULT = true;
|
||||
|
||||
/**
|
||||
* Whether to always auto-complete email addresses for sending MMS. By default, Bugle starts
|
||||
* to auto-complete after the user has typed the "@" character.
|
||||
* Default is (@value ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS_DEFAULT}.
|
||||
*/
|
||||
public static final String ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS =
|
||||
"bugle_always_autocomplete_email_address";
|
||||
public static final boolean ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS_DEFAULT = false;
|
||||
|
||||
// We typically request an aspect ratio close the the screen size, but some cameras can be
|
||||
// flaky and not work well in certain aspect ratios. This allows us to guide the CameraManager
|
||||
// to pick a more reliable aspect ratio. The value is a float like 1.333f or 1.777f. There is
|
||||
// no hard coded default because the default is the screen aspect ratio.
|
||||
public static final String CAMERA_ASPECT_RATIO = "bugle_camera_aspect_ratio";
|
||||
|
||||
/**
|
||||
* The recent time range within which we should check MMS WAP Push duplication
|
||||
* If the value is 0, it signals that we should use old dedup algorithm for wap push
|
||||
*/
|
||||
public static final String MMS_WAP_PUSH_DEDUP_TIME_LIMIT_SECS =
|
||||
"bugle_mms_wap_push_dedup_time_limit_secs";
|
||||
public static final long MMS_WAP_PUSH_DEDUP_TIME_LIMIT_SECS_DEFAULT = 7 * 24 * 3600; // 7 days
|
||||
|
||||
/**
|
||||
* Whether to use persistent, on-disk LogSaver
|
||||
*/
|
||||
public static final String PERSISTENT_LOGSAVER = "bugle_persistent_logsaver";
|
||||
public static final boolean PERSISTENT_LOGSAVER_DEFAULT = false;
|
||||
|
||||
/**
|
||||
* For in-memory LogSaver, what's the size of memory buffer in number of records
|
||||
*/
|
||||
public static final String IN_MEMORY_LOGSAVER_RECORD_COUNT =
|
||||
"bugle_in_memory_logsaver_record_count";
|
||||
public static final int IN_MEMORY_LOGSAVER_RECORD_COUNT_DEFAULT = 500;
|
||||
|
||||
/**
|
||||
* For on-disk LogSaver, what's the size of file rotation set
|
||||
*/
|
||||
public static final String PERSISTENT_LOGSAVER_ROTATION_SET_SIZE =
|
||||
"bugle_persistent_logsaver_rotation_set_size";
|
||||
public static final int PERSISTENT_LOGSAVER_ROTATION_SET_SIZE_DEFAULT = 8;
|
||||
|
||||
/**
|
||||
* For on-disk LogSaver, what's the byte limit of a single log file
|
||||
*/
|
||||
public static final String PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES =
|
||||
"bugle_persistent_logsaver_file_limit";
|
||||
public static final int PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES_DEFAULT = 256 * 1024; // 256KB
|
||||
|
||||
/**
|
||||
* We concatenate all text parts in an MMS to form the message text. This specifies
|
||||
* the separator between the combinated text parts. Default is ' ' (space).
|
||||
*/
|
||||
public static final String MMS_TEXT_CONCAT_SEPARATOR = "bugle_mms_text_concat_separator";
|
||||
public static final String MMS_TEXT_CONCAT_SEPARATOR_DEFAULT = " ";
|
||||
|
||||
/**
|
||||
* Whether to enable transcoding GIFs. We sometimes need to compress GIFs to make them small
|
||||
* enough to send via MMS (which often limits messages to 1 MB in size).
|
||||
*/
|
||||
public static final String ENABLE_GIF_TRANSCODING = "bugle_gif_transcoding";
|
||||
public static final boolean ENABLE_GIF_TRANSCODING_DEFAULT = true;
|
||||
}
|
||||
|
||||
@@ -17,304 +17,22 @@
|
||||
|
||||
package com.android.messaging.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.FragmentManager;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.telephony.SmsMessage;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.messaging.Factory;
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.datamodel.SyncManager;
|
||||
import com.android.messaging.datamodel.action.DumpDatabaseAction;
|
||||
import com.android.messaging.datamodel.action.LogTelephonyDatabaseAction;
|
||||
import com.android.messaging.sms.MmsUtils;
|
||||
import com.android.messaging.ui.UIIntents;
|
||||
import com.android.messaging.ui.debug.DebugSmsMmsFromDumpFileDialogFragment;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StreamCorruptedException;
|
||||
|
||||
public class DebugUtils {
|
||||
private static final String TAG = "bugle.util.DebugUtils";
|
||||
|
||||
private static boolean sDebugNoise;
|
||||
private static boolean sDebugClassZeroSms;
|
||||
private static MediaPlayer [] sMediaPlayer;
|
||||
private static final Object sLock = new Object();
|
||||
|
||||
public static final int DEBUG_SOUND_SERVER_REQUEST = 0;
|
||||
public static final int DEBUG_SOUND_DB_OP = 1;
|
||||
|
||||
public static void maybePlayDebugNoise(final Context context, final int sound) {
|
||||
if (sDebugNoise) {
|
||||
synchronized (sLock) {
|
||||
try {
|
||||
if (sMediaPlayer == null) {
|
||||
sMediaPlayer = new MediaPlayer[2];
|
||||
sMediaPlayer[DEBUG_SOUND_SERVER_REQUEST] =
|
||||
MediaPlayer.create(context, R.raw.server_request_debug);
|
||||
sMediaPlayer[DEBUG_SOUND_DB_OP] =
|
||||
MediaPlayer.create(context, R.raw.db_op_debug);
|
||||
sMediaPlayer[DEBUG_SOUND_DB_OP].setVolume(1.0F, 1.0F);
|
||||
sMediaPlayer[DEBUG_SOUND_SERVER_REQUEST].setVolume(0.3F, 0.3F);
|
||||
}
|
||||
if (sMediaPlayer[sound] != null) {
|
||||
sMediaPlayer[sound].start();
|
||||
}
|
||||
} catch (final IllegalArgumentException e) {
|
||||
LogUtil.e(TAG, "MediaPlayer exception", e);
|
||||
} catch (final SecurityException e) {
|
||||
LogUtil.e(TAG, "MediaPlayer exception", e);
|
||||
} catch (final IllegalStateException e) {
|
||||
LogUtil.e(TAG, "MediaPlayer exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isDebugEnabled() {
|
||||
return BugleGservices.get().getBoolean(BugleGservicesKeys.ENABLE_DEBUGGING_FEATURES,
|
||||
BugleGservicesKeys.ENABLE_DEBUGGING_FEATURES_DEFAULT);
|
||||
}
|
||||
|
||||
public abstract static class DebugAction {
|
||||
final String mTitle;
|
||||
public DebugAction(final String title) {
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
public abstract void run();
|
||||
}
|
||||
|
||||
public static void showDebugOptions(final Activity host) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(host);
|
||||
|
||||
final ArrayAdapter<DebugAction> arrayAdapter = new ArrayAdapter<DebugAction>(
|
||||
host, android.R.layout.simple_list_item_1);
|
||||
|
||||
arrayAdapter.add(new DebugAction("Dump Database") {
|
||||
@Override
|
||||
public void run() {
|
||||
DumpDatabaseAction.dumpDatabase();
|
||||
}
|
||||
});
|
||||
|
||||
arrayAdapter.add(new DebugAction("Log Telephony Data") {
|
||||
@Override
|
||||
public void run() {
|
||||
LogTelephonyDatabaseAction.dumpDatabase();
|
||||
}
|
||||
});
|
||||
|
||||
arrayAdapter.add(new DebugAction("Toggle Noise") {
|
||||
@Override
|
||||
public void run() {
|
||||
sDebugNoise = !sDebugNoise;
|
||||
}
|
||||
});
|
||||
|
||||
arrayAdapter.add(new DebugAction("Force sync SMS") {
|
||||
@Override
|
||||
public void run() {
|
||||
final BuglePrefs prefs = BuglePrefs.getApplicationPrefs();
|
||||
prefs.putLong(BuglePrefsKeys.LAST_FULL_SYNC_TIME, -1);
|
||||
SyncManager.forceSync();
|
||||
}
|
||||
});
|
||||
|
||||
arrayAdapter.add(new DebugAction("Sync SMS") {
|
||||
@Override
|
||||
public void run() {
|
||||
SyncManager.sync();
|
||||
}
|
||||
});
|
||||
|
||||
arrayAdapter.add(new DebugAction("Load SMS/MMS from dump file") {
|
||||
@Override
|
||||
public void run() {
|
||||
new DebugSmsMmsDumpTask(host,
|
||||
DebugSmsMmsFromDumpFileDialogFragment.ACTION_LOAD).executeOnThreadPool();
|
||||
}
|
||||
});
|
||||
|
||||
arrayAdapter.add(new DebugAction("Email SMS/MMS dump file") {
|
||||
@Override
|
||||
public void run() {
|
||||
new DebugSmsMmsDumpTask(host,
|
||||
DebugSmsMmsFromDumpFileDialogFragment.ACTION_EMAIL).executeOnThreadPool();
|
||||
}
|
||||
});
|
||||
|
||||
arrayAdapter.add(new DebugAction("MMS Config...") {
|
||||
@Override
|
||||
public void run() {
|
||||
UIIntents.get().launchDebugMmsConfigActivity(host);
|
||||
}
|
||||
});
|
||||
|
||||
arrayAdapter.add(new DebugAction(sDebugClassZeroSms ? "Turn off Class 0 sms test" :
|
||||
"Turn on Class Zero test") {
|
||||
@Override
|
||||
public void run() {
|
||||
sDebugClassZeroSms = !sDebugClassZeroSms;
|
||||
}
|
||||
});
|
||||
|
||||
arrayAdapter.add(new DebugAction("Test sharing a file URI") {
|
||||
@Override
|
||||
public void run() {
|
||||
shareFileUri();
|
||||
}
|
||||
});
|
||||
|
||||
builder.setAdapter(arrayAdapter, (arg0, pos) -> arrayAdapter.getItem(pos).run());
|
||||
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Task to list all the dump files and perform an action on it
|
||||
*/
|
||||
private static class DebugSmsMmsDumpTask extends SafeAsyncTask<Void, Void, String[]> {
|
||||
private final String mAction;
|
||||
private final Activity mHost;
|
||||
|
||||
public DebugSmsMmsDumpTask(final Activity host, final String action) {
|
||||
mHost = host;
|
||||
mAction = action;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final String[] result) {
|
||||
if (result == null || result.length < 1) {
|
||||
return;
|
||||
}
|
||||
final FragmentManager fragmentManager = mHost.getFragmentManager();
|
||||
final FragmentTransaction ft = fragmentManager.beginTransaction();
|
||||
final DebugSmsMmsFromDumpFileDialogFragment dialog =
|
||||
DebugSmsMmsFromDumpFileDialogFragment.newInstance(result, mAction);
|
||||
dialog.show(fragmentManager, ""/*tag*/);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] doInBackgroundTimed(final Void... params) {
|
||||
final File dir = DebugUtils.getDebugFilesDir();
|
||||
return dir.list((dir1, filename) -> filename != null
|
||||
&& ((mAction == DebugSmsMmsFromDumpFileDialogFragment.ACTION_EMAIL
|
||||
&& filename.equals(DumpDatabaseAction.DUMP_NAME))
|
||||
|| filename.startsWith(MmsUtils.MMS_DUMP_PREFIX)
|
||||
|| filename.startsWith(MmsUtils.SMS_DUMP_PREFIX)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the received raw SMS data into a file on external storage
|
||||
*
|
||||
* @param id The ID to use as part of the dump file name
|
||||
* @param messages The raw SMS data
|
||||
*/
|
||||
public static void dumpSms(final long id, final android.telephony.SmsMessage[] messages,
|
||||
final String format) {
|
||||
try {
|
||||
final String dumpFileName = MmsUtils.SMS_DUMP_PREFIX + id;
|
||||
final File dumpFile = DebugUtils.getDebugFile(dumpFileName, true);
|
||||
if (dumpFile != null) {
|
||||
final FileOutputStream fos = new FileOutputStream(dumpFile);
|
||||
final DataOutputStream dos = new DataOutputStream(fos);
|
||||
try {
|
||||
final int chars = (TextUtils.isEmpty(format) ? 0 : format.length());
|
||||
dos.writeInt(chars);
|
||||
if (chars > 0) {
|
||||
dos.writeUTF(format);
|
||||
}
|
||||
dos.writeInt(messages.length);
|
||||
for (final android.telephony.SmsMessage message : messages) {
|
||||
final byte[] pdu = message.getPdu();
|
||||
dos.writeInt(pdu.length);
|
||||
dos.write(pdu, 0, pdu.length);
|
||||
}
|
||||
dos.flush();
|
||||
} finally {
|
||||
dos.close();
|
||||
ensureReadable(dumpFile);
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
LogUtil.e(LogUtil.BUGLE_TAG, "dumpSms: " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load MMS/SMS from the dump file
|
||||
*/
|
||||
public static SmsMessage[] retreiveSmsFromDumpFile(final String dumpFileName) {
|
||||
SmsMessage[] messages = null;
|
||||
final File inputFile = DebugUtils.getDebugFile(dumpFileName, false);
|
||||
if (inputFile != null) {
|
||||
FileInputStream fis = null;
|
||||
DataInputStream dis = null;
|
||||
try {
|
||||
fis = new FileInputStream(inputFile);
|
||||
dis = new DataInputStream(fis);
|
||||
|
||||
// SMS dump
|
||||
String format = null;
|
||||
final int chars = dis.readInt();
|
||||
if (chars > 0) {
|
||||
format = dis.readUTF();
|
||||
}
|
||||
final int count = dis.readInt();
|
||||
final SmsMessage[] messagesTemp = new SmsMessage[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
final int length = dis.readInt();
|
||||
final byte[] pdu = new byte[length];
|
||||
dis.read(pdu, 0, length);
|
||||
messagesTemp[i] = SmsMessage.createFromPdu(pdu, format);
|
||||
}
|
||||
messages = messagesTemp;
|
||||
} catch (final FileNotFoundException e) {
|
||||
// Nothing to do
|
||||
} catch (final StreamCorruptedException e) {
|
||||
// Nothing to do
|
||||
} catch (final IOException e) {
|
||||
// Nothing to do
|
||||
} finally {
|
||||
if (dis != null) {
|
||||
try {
|
||||
dis.close();
|
||||
} catch (final IOException e) {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
public static File getDebugFile(final String fileName, final boolean create) {
|
||||
final File dir = getDebugFilesDir();
|
||||
final File file = new File(dir, fileName);
|
||||
@@ -416,24 +134,4 @@ public class DebugUtils {
|
||||
// Never found ourself in the stack?!
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating whether ClassZero debugging is enabled. If enabled, any received
|
||||
* sms is treated as if it were a class zero message and displayed by the ClassZeroActivity.
|
||||
*/
|
||||
public static boolean debugClassZeroSmsEnabled() {
|
||||
return sDebugClassZeroSms;
|
||||
}
|
||||
|
||||
/** Shares a ringtone file via file URI. */
|
||||
private static void shareFileUri() {
|
||||
final String packageName = "com.android.messaging";
|
||||
final String fileName = "/system/media/audio/ringtones/Andromeda.ogg";
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setPackage(packageName);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + fileName));
|
||||
intent.setType("image/*");
|
||||
Factory.get().getApplicationContext().startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,6 @@ public class GifTranscoder {
|
||||
}
|
||||
|
||||
public static boolean transcode(Context context, String filePath, String outFilePath) {
|
||||
if (!isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
final long inputSize = new File(filePath).length();
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
final boolean success = transcodeInternal(filePath, outFilePath);
|
||||
@@ -77,19 +74,6 @@ public class GifTranscoder {
|
||||
}
|
||||
|
||||
public static boolean canBeTranscoded(int width, int height) {
|
||||
if (!isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
return width >= MIN_WIDTH && height >= MIN_HEIGHT;
|
||||
}
|
||||
|
||||
private static boolean isEnabled() {
|
||||
final boolean enabled = BugleGservices.get().getBoolean(
|
||||
BugleGservicesKeys.ENABLE_GIF_TRANSCODING,
|
||||
BugleGservicesKeys.ENABLE_GIF_TRANSCODING_DEFAULT);
|
||||
if (!enabled) {
|
||||
LogUtil.w(TAG, "GIF transcoding is disabled");
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.messaging.util;
|
||||
|
||||
import android.os.Process;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.messaging.Factory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Save the app's own log to dump along with adb bugreport
|
||||
*/
|
||||
public abstract class LogSaver {
|
||||
/**
|
||||
* Writes the accumulated log entries, from oldest to newest, to the specified PrintWriter.
|
||||
* Log lines are emitted in much the same form as logcat -v threadtime -- specifically,
|
||||
* lines will include a timestamp, pid, tid, level, and tag.
|
||||
*
|
||||
* @param writer The PrintWriter to output
|
||||
*/
|
||||
public abstract void dump(PrintWriter writer);
|
||||
|
||||
/**
|
||||
* Log a line
|
||||
*
|
||||
* @param level The log level to use
|
||||
* @param tag The log tag
|
||||
* @param msg The message of the log line
|
||||
*/
|
||||
public abstract void log(int level, String tag, String msg);
|
||||
|
||||
/**
|
||||
* Check if the LogSaver still matches the current Gservices settings
|
||||
*
|
||||
* @return true if matches, false otherwise
|
||||
*/
|
||||
public abstract boolean isCurrent();
|
||||
|
||||
private LogSaver() {
|
||||
}
|
||||
|
||||
public static LogSaver newInstance() {
|
||||
final boolean persistent = BugleGservices.get().getBoolean(
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER,
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER_DEFAULT);
|
||||
if (persistent) {
|
||||
final int setSize = BugleGservices.get().getInt(
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER_ROTATION_SET_SIZE,
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER_ROTATION_SET_SIZE_DEFAULT);
|
||||
final int fileLimitBytes = BugleGservices.get().getInt(
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES,
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES_DEFAULT);
|
||||
return new DiskLogSaver(setSize, fileLimitBytes);
|
||||
} else {
|
||||
final int size = BugleGservices.get().getInt(
|
||||
BugleGservicesKeys.IN_MEMORY_LOGSAVER_RECORD_COUNT,
|
||||
BugleGservicesKeys.IN_MEMORY_LOGSAVER_RECORD_COUNT_DEFAULT);
|
||||
return new MemoryLogSaver(size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A circular in-memory log to be used to log potentially verbose logs. The logs will be
|
||||
* persisted in memory in the application and can be dumped by various dump() methods.
|
||||
* For example, adb shell dumpsys activity provider com.android.messaging.
|
||||
* The dump will also show up in bugreports.
|
||||
*/
|
||||
private static final class MemoryLogSaver extends LogSaver {
|
||||
/**
|
||||
* Record to store a single log entry. Stores timestamp, tid, level, tag, and message.
|
||||
* It can be reused when the circular log rolls over. This avoids creating new objects.
|
||||
*/
|
||||
private static class LogRecord {
|
||||
int mTid;
|
||||
String mLevelString;
|
||||
long mTimeMillis; // from System.currentTimeMillis
|
||||
String mTag;
|
||||
String mMessage;
|
||||
|
||||
LogRecord() {
|
||||
}
|
||||
|
||||
void set(int tid, int level, long time, String tag, String message) {
|
||||
this.mTid = tid;
|
||||
this.mTimeMillis = time;
|
||||
this.mTag = tag;
|
||||
this.mMessage = message;
|
||||
this.mLevelString = getLevelString(level);
|
||||
}
|
||||
}
|
||||
|
||||
private final int mSize;
|
||||
private final CircularArray<LogRecord> mLogList;
|
||||
private final Object mLock;
|
||||
|
||||
private final SimpleDateFormat mSdf = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
|
||||
|
||||
public MemoryLogSaver(final int size) {
|
||||
mSize = size;
|
||||
mLogList = new CircularArray<LogRecord>(size);
|
||||
mLock = new Object();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(PrintWriter writer) {
|
||||
int pid = Process.myPid();
|
||||
synchronized (mLock) {
|
||||
for (int i = 0; i < mLogList.count(); i++) {
|
||||
LogRecord rec = mLogList.get(i);
|
||||
writer.println(String.format("%s %5d %5d %s %s: %s",
|
||||
mSdf.format(rec.mTimeMillis),
|
||||
pid, rec.mTid, rec.mLevelString, rec.mTag, rec.mMessage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(int level, String tag, String msg) {
|
||||
synchronized (mLock) {
|
||||
LogRecord rec = mLogList.getFree();
|
||||
if (rec == null) {
|
||||
rec = new LogRecord();
|
||||
}
|
||||
rec.set(Process.myTid(), level, System.currentTimeMillis(), tag, msg);
|
||||
mLogList.add(rec);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() {
|
||||
final boolean persistent = BugleGservices.get().getBoolean(
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER,
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER_DEFAULT);
|
||||
if (persistent) {
|
||||
return false;
|
||||
}
|
||||
final int size = BugleGservices.get().getInt(
|
||||
BugleGservicesKeys.IN_MEMORY_LOGSAVER_RECORD_COUNT,
|
||||
BugleGservicesKeys.IN_MEMORY_LOGSAVER_RECORD_COUNT_DEFAULT);
|
||||
return size == mSize;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A persistent, on-disk log saver. It uses the standard Java util logger along with
|
||||
* a rotation log file set to store the logs in app's local file directory "app_logs".
|
||||
*/
|
||||
private static final class DiskLogSaver extends LogSaver {
|
||||
private static final String DISK_LOG_DIR_NAME = "logs";
|
||||
|
||||
private final int mSetSize;
|
||||
private final int mFileLimitBytes;
|
||||
private Logger mDiskLogger;
|
||||
|
||||
public DiskLogSaver(final int setSize, final int fileLimitBytes) {
|
||||
Assert.isTrue(setSize > 0);
|
||||
Assert.isTrue(fileLimitBytes > 0);
|
||||
mSetSize = setSize;
|
||||
mFileLimitBytes = fileLimitBytes;
|
||||
initDiskLog();
|
||||
}
|
||||
|
||||
private static void clearDefaultHandlers(Logger logger) {
|
||||
Assert.notNull(logger);
|
||||
for (Handler handler : logger.getHandlers()) {
|
||||
logger.removeHandler(handler);
|
||||
}
|
||||
}
|
||||
|
||||
private void initDiskLog() {
|
||||
mDiskLogger = Logger.getLogger(LogUtil.BUGLE_TAG);
|
||||
// We don't want the default console handler
|
||||
clearDefaultHandlers(mDiskLogger);
|
||||
// Don't want duplicate print in system log
|
||||
mDiskLogger.setUseParentHandlers(false);
|
||||
// FileHandler manages the log files in a fixed rotation set
|
||||
final File logDir = Factory.get().getApplicationContext().getDir(
|
||||
DISK_LOG_DIR_NAME, 0/*mode*/);
|
||||
FileHandler handler = null;
|
||||
try {
|
||||
handler = new FileHandler(
|
||||
logDir + "/%g.log", mFileLimitBytes, mSetSize, true/*append*/);
|
||||
} catch (Exception e) {
|
||||
Log.e(LogUtil.BUGLE_TAG, "LogSaver: fail to init disk logger", e);
|
||||
return;
|
||||
}
|
||||
final Formatter formatter = new Formatter() {
|
||||
@Override
|
||||
public String format(java.util.logging.LogRecord r) {
|
||||
return r.getMessage();
|
||||
}
|
||||
};
|
||||
handler.setFormatter(formatter);
|
||||
handler.setLevel(Level.ALL);
|
||||
mDiskLogger.addHandler(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(PrintWriter writer) {
|
||||
for (int i = mSetSize - 1; i >= 0; i--) {
|
||||
final File logDir = Factory.get().getApplicationContext().getDir(
|
||||
DISK_LOG_DIR_NAME, 0/*mode*/);
|
||||
final String logFilePath = logDir + "/" + i + ".log";
|
||||
try {
|
||||
final File logFile = new File(logFilePath);
|
||||
if (!logFile.exists()) {
|
||||
continue;
|
||||
}
|
||||
final BufferedReader reader = new BufferedReader(new FileReader(logFile));
|
||||
for (String line; (line = reader.readLine()) != null;) {
|
||||
line = line.trim();
|
||||
writer.println(line);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.w(LogUtil.BUGLE_TAG, "LogSaver: can not find log file " + logFilePath);
|
||||
} catch (IOException e) {
|
||||
Log.w(LogUtil.BUGLE_TAG, "LogSaver: can not read log file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(int level, String tag, String msg) {
|
||||
final SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
|
||||
mDiskLogger.info(String.format("%s %5d %5d %s %s: %s\n",
|
||||
sdf.format(System.currentTimeMillis()),
|
||||
Process.myPid(), Process.myTid(), getLevelString(level), tag, msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() {
|
||||
final boolean persistent = BugleGservices.get().getBoolean(
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER,
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER_DEFAULT);
|
||||
if (!persistent) {
|
||||
return false;
|
||||
}
|
||||
final int setSize = BugleGservices.get().getInt(
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER_ROTATION_SET_SIZE,
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER_ROTATION_SET_SIZE_DEFAULT);
|
||||
final int fileLimitBytes = BugleGservices.get().getInt(
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES,
|
||||
BugleGservicesKeys.PERSISTENT_LOGSAVER_FILE_LIMIT_BYTES_DEFAULT);
|
||||
return setSize == mSetSize && fileLimitBytes == mFileLimitBytes;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getLevelString(final int level) {
|
||||
switch (level) {
|
||||
case android.util.Log.DEBUG:
|
||||
return "D";
|
||||
case android.util.Log.WARN:
|
||||
return "W";
|
||||
case android.util.Log.INFO:
|
||||
return "I";
|
||||
case android.util.Log.VERBOSE:
|
||||
return "V";
|
||||
case android.util.Log.ERROR:
|
||||
return "E";
|
||||
case android.util.Log.ASSERT:
|
||||
return "A";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,33 +36,6 @@ public class LogUtil {
|
||||
public static final int INFO = android.util.Log.INFO;
|
||||
public static final int ERROR = android.util.Log.ERROR;
|
||||
|
||||
// If this is non-null, DEBUG and higher logs will be tracked in-memory. It will not include
|
||||
// VERBOSE logs.
|
||||
private static LogSaver sDebugLogSaver;
|
||||
private static volatile boolean sCaptureDebugLogs;
|
||||
|
||||
/**
|
||||
* Read Gservices to see if logging should be enabled.
|
||||
*/
|
||||
public static void refreshGservices(final BugleGservices gservices) {
|
||||
sCaptureDebugLogs = gservices.getBoolean(
|
||||
BugleGservicesKeys.ENABLE_LOG_SAVER,
|
||||
BugleGservicesKeys.ENABLE_LOG_SAVER_DEFAULT);
|
||||
if (sCaptureDebugLogs && (sDebugLogSaver == null || !sDebugLogSaver.isCurrent())) {
|
||||
// We were not capturing logs before. We are now.
|
||||
sDebugLogSaver = LogSaver.newInstance();
|
||||
} else if (!sCaptureDebugLogs && sDebugLogSaver != null) {
|
||||
// We were capturing logs. We aren't anymore.
|
||||
sDebugLogSaver = null;
|
||||
}
|
||||
}
|
||||
|
||||
// This is called from FactoryImpl once the Gservices class is initialized.
|
||||
public static void initializeGservices (final BugleGservices gservices) {
|
||||
gservices.registerForChanges(() -> refreshGservices(gservices));
|
||||
refreshGservices(gservices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #VERBOSE} log message.
|
||||
* @param tag Used to identify the source of a log message. It usually identifies
|
||||
@@ -214,26 +187,6 @@ public class LogUtil {
|
||||
*/
|
||||
private static void println(final int level, final String tag, final String msg) {
|
||||
android.util.Log.println(level, tag, msg);
|
||||
|
||||
LogSaver serviceLog = sDebugLogSaver;
|
||||
if (serviceLog != null && level >= android.util.Log.DEBUG) {
|
||||
serviceLog.log(level, tag, msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save logging into LogSaver only, for dumping to bug report
|
||||
*
|
||||
* @param level The priority/type of this log message
|
||||
* @param tag Used to identify the source of a log message. It usually identifies
|
||||
* the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
*/
|
||||
public static void save(final int level, final String tag, final String msg) {
|
||||
LogSaver serviceLog = sDebugLogSaver;
|
||||
if (serviceLog != null) {
|
||||
serviceLog.log(level, tag, msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,11 +213,4 @@ public class LogUtil {
|
||||
return "Redacted-" + text.length();
|
||||
}
|
||||
}
|
||||
|
||||
public static void dump(java.io.PrintWriter out) {
|
||||
final LogSaver logsaver = sDebugLogSaver;
|
||||
if (logsaver != null) {
|
||||
logsaver.dump(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2024 The LineageOS Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -59,8 +60,6 @@ public class LoggingTimer {
|
||||
|
||||
final String logMessage = String.format("Used %dms for %s", elapsedMs, mName);
|
||||
|
||||
LogUtil.save(LogUtil.DEBUG, mTag, logMessage);
|
||||
|
||||
if (mWarnLimitMillis != NO_WARN_LIMIT && elapsedMs > mWarnLimitMillis) {
|
||||
LogUtil.w(mTag, logMessage);
|
||||
} else if (LogUtil.isLoggable(mTag, LogUtil.VERBOSE)) {
|
||||
|
||||
Reference in New Issue
Block a user