diff options
author | tnmy-cyngn <tlnu@cyngn.com> | 2016-04-15 02:46:22 +0530 |
---|---|---|
committer | Gerrit Code Review <gerrit@cyanogenmod.org> | 2016-04-22 12:56:22 -0700 |
commit | 22d92d6675a139bf63613788f19f06ed59449315 (patch) | |
tree | c104e47243cbcb05e6c039ca8c4d2f2a67b28040 | |
parent | 98df70d4e4210517bc810df59e7a956a5688f9b0 (diff) | |
download | packages_apps_Messaging-22d92d6675a139bf63613788f19f06ed59449315.zip packages_apps_Messaging-22d92d6675a139bf63613788f19f06ed59449315.tar.gz packages_apps_Messaging-22d92d6675a139bf63613788f19f06ed59449315.tar.bz2 |
Text/Multimedia message limit feature
Porting feature from 12.1 to 13.1
Feature to set/configure SMS and MMS limits per
conversation.
Bug: PAELLA-194,PAELLA-195
Change-Id: Ib1bd15f58a3d33572484d8c28de42e481c66f6b0
18 files changed, 685 insertions, 6 deletions
diff --git a/res/layout/number_picker_dialog.xml b/res/layout/number_picker_dialog.xml new file mode 100644 index 0000000..b94f9ad --- /dev/null +++ b/res/layout/number_picker_dialog.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2009, Google Inc. +** +** 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 layout file is used by the AlertDialog when displaying a list of items. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:gravity="center_horizontal" + android:layout_width="wrap_content" + android:layout_height="match_parent" > + + <TextView + android:id="@+id/header" + android:gravity="center_horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="1dip" /> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:paddingTop="10dip" + android:orientation="horizontal"> + + <NumberPicker + android:id="@+id/number_picker" + android:layout_width="100dip" + android:layout_height="150dip" /> + + <TextView + android:id="@+id/unit" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="10dp" + android:layout_gravity="center_vertical" + android:visibility="gone" /> + + </LinearLayout> + +</LinearLayout> diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml index 674e3ec..4ad47e2 100644 --- a/res/values/cm_strings.xml +++ b/res/values/cm_strings.xml @@ -46,6 +46,18 @@ <string name="priority_normal">Normal</string> <string name="priority_high">High</string> + <!-- Storage specific Settings --> + <string name="sms_storage_pref_title">Storage</string> + <string name="pref_summary_auto_delete">Delete old messages as limits are reached</string> + <string name="auto_delete_pref_title">Delete old messages</string> + <string name="pref_summary_delete_limit"><xliff:g id="count">%1$s</xliff:g> messages per conversation</string> + <string name="sms_delete_pref_title">Text message limit</string> + <string name="mms_delete_pref_title">Multimedia message limit</string> + <string name="set">Set</string> + <string name="no">Cancel</string> + <string name="pref_messages_to_save">Set number of messages to save</string> + + <!-- Swipe to delete conversation --> <string name="swipe_to_delete_conversation_pref_title">Swipe to delete</string> <string name="swipe_to_delete_conversation_pref_summary">Swipe to the right to delete a conversation</string> diff --git a/res/xml-v21/preferences_application.xml b/res/xml-v21/preferences_application.xml index 8acbae1..4d39999 100644 --- a/res/xml-v21/preferences_application.xml +++ b/res/xml-v21/preferences_application.xml @@ -119,6 +119,32 @@ android:defaultValue="false" android:persistent="true" /> + <!--Storage Preferences--> + <PreferenceCategory + android:title="@string/sms_storage_pref_title" + android:key="storage_settings_pref_key"> + + <SwitchPreference + android:defaultValue="true" + android:key="auto_delete_pref_key" + android:summary="@string/pref_summary_auto_delete" + android:title="@string/auto_delete_pref_title" /> + + <Preference + android:key="sms_delete_limit_pref_key" + android:dependency="auto_delete_pref_key" + android:persistent="false" + android:summary="@string/pref_summary_delete_limit" + android:title="@string/sms_delete_pref_title" /> + + <Preference + android:key="mms_delete_limit_pref_key" + android:dependency="auto_delete_pref_key" + android:persistent="false" + android:summary="@string/pref_summary_delete_limit" + android:title="@string/mms_delete_pref_title" /> + </PreferenceCategory> + <!-- QuickMessage settings --> <PreferenceCategory android:title="@string/pref_quickmessage"> diff --git a/res/xml-v23/preferences_application.xml b/res/xml-v23/preferences_application.xml index 29a5a91..95ba3c3 100644 --- a/res/xml-v23/preferences_application.xml +++ b/res/xml-v23/preferences_application.xml @@ -121,6 +121,32 @@ android:defaultValue="false" android:persistent="true" /> + <!--Storage Preferences--> + <PreferenceCategory + android:title="@string/sms_storage_pref_title" + android:key="storage_settings_pref_key"> + + <SwitchPreference + android:defaultValue="true" + android:key="auto_delete_pref_key" + android:summary="@string/pref_summary_auto_delete" + android:title="@string/auto_delete_pref_title" /> + + <Preference + android:key="sms_delete_limit_pref_key" + android:dependency="auto_delete_pref_key" + android:persistent="false" + android:summary="@string/pref_summary_delete_limit" + android:title="@string/sms_delete_pref_title" /> + + <Preference + android:key="mms_delete_limit_pref_key" + android:dependency="auto_delete_pref_key" + android:persistent="false" + android:summary="@string/pref_summary_delete_limit" + android:title="@string/mms_delete_pref_title" /> + </PreferenceCategory> + <!-- QuickMessage settings --> <PreferenceCategory android:title="@string/pref_quickmessage"> diff --git a/res/xml/preferences_application.xml b/res/xml/preferences_application.xml index 0e8aa45..64bc7e2 100644 --- a/res/xml/preferences_application.xml +++ b/res/xml/preferences_application.xml @@ -119,6 +119,32 @@ android:defaultValue="false" android:persistent="true" /> + <!--Storage Preferences--> + <PreferenceCategory + android:title="@string/sms_storage_pref_title" + android:key="storage_settings_pref_key"> + + <SwitchPreference + android:defaultValue="true" + android:key="auto_delete_pref_key" + android:summary="@string/pref_summary_auto_delete" + android:title="@string/auto_delete_pref_title" /> + + <Preference + android:key="sms_delete_limit_pref_key" + android:dependency="auto_delete_pref_key" + android:persistent="false" + android:summary="@string/pref_summary_delete_limit" + android:title="@string/sms_delete_pref_title" /> + + <Preference + android:key="mms_delete_limit_pref_key" + android:dependency="auto_delete_pref_key" + android:persistent="false" + android:summary="@string/pref_summary_delete_limit" + android:title="@string/mms_delete_pref_title" /> + </PreferenceCategory> + <!-- QuickMessage settings --> <PreferenceCategory android:title="@string/pref_quickmessage"> diff --git a/src/android/support/v7/mms/CarrierConfigValuesLoader.java b/src/android/support/v7/mms/CarrierConfigValuesLoader.java index ad94fb2..e9798d2 100644 --- a/src/android/support/v7/mms/CarrierConfigValuesLoader.java +++ b/src/android/support/v7/mms/CarrierConfigValuesLoader.java @@ -195,4 +195,24 @@ public interface CarrierConfigValuesLoader { */ public static final String CONFIG_NAI_SUFFIX = "naiSuffix"; public static final String CONFIG_NAI_SUFFIX_DEFAULT = null; + /** + * Integer value: default limit for number of SMS per conversation + */ + public static final String CONFIG_SMS_MESSAGES_PER_THREAD = "defaultSMSMessagesPerThread"; + public static final int CONFIG_SMS_MESSAGES_PER_THREAD_DEFAULT = 10000; + /** + * Integer value: default limit for number of MMS per conversation + */ + public static final String CONFIG_MMS_MESSAGES_PER_THREAD = "defaultMMSMessagesPerThread"; + public static final int CONFIG_MMS_MESSAGES_PER_THREAD_DEFAULT = 1000; + /** + * Integer value: minimum limit for number of messages per conversation + */ + public static final String CONFIG_MIN_MESSAGE_COUNT_PER_THREAD = "minMessageCountPerThread"; + public static final int CONFIG_MIN_MESSAGE_COUNT_PER_THREAD_DEFAULT = 10; + /** + * Integer value: maximum limit for number of messages per conversation + */ + public static final String CONFIG_MAX_MESSAGE_COUNT_PER_THREAD = "maxMessageCountPerThread"; + public static final int CONFIG_MAX_MESSAGE_COUNT_PER_THREAD_DEFAULT = 10000; } diff --git a/src/com/android/messaging/datamodel/BugleDatabaseOperations.java b/src/com/android/messaging/datamodel/BugleDatabaseOperations.java index 9faf3d5..f80abdf 100644 --- a/src/com/android/messaging/datamodel/BugleDatabaseOperations.java +++ b/src/com/android/messaging/datamodel/BugleDatabaseOperations.java @@ -1939,4 +1939,67 @@ public class BugleDatabaseOperations { Assert.inRange(count, 0, 1); return (count >= 0); } + + @DoesNotRunOnMainThread + public static boolean deleteConversationByProtocol(final DatabaseWrapper dbWrapper, + final String conversationId, final long cutoffTimestamp, final int protocol) { + if (protocol != MessageData.PROTOCOL_SMS && protocol != MessageData.PROTOCOL_MMS) { + return false; + } + + Assert.isNotMainThread(); + dbWrapper.beginTransaction(); + boolean conversationDeleted = false; + boolean conversationMessagesDeleted; + try { + // Delete all messages prior to the cutoff + dbWrapper.delete(DatabaseHelper.MESSAGES_TABLE, + MessageColumns.CONVERSATION_ID + "=? AND " + + MessageColumns.RECEIVED_TIMESTAMP + "<=? AND " + + MessageColumns.PROTOCOL + "=?", + new String[] { conversationId, Long.toString(cutoffTimestamp), + Integer.toString(protocol) }); + // Check to see if there are any messages left in the conversation + final long count = dbWrapper.queryNumEntries(DatabaseHelper.MESSAGES_TABLE, + MessageColumns.CONVERSATION_ID + "=?", new String[] { conversationId }); + conversationMessagesDeleted = (count <= 0); + + if (conversationMessagesDeleted) { + // Delete conversation row + final int conversationCount = dbWrapper.delete(DatabaseHelper.CONVERSATIONS_TABLE, + ConversationColumns._ID + "=?", new String[] { conversationId }); + conversationDeleted = (conversationCount > 0); + } + dbWrapper.setTransactionSuccessful(); + } finally { + dbWrapper.endTransaction(); + } + return conversationDeleted; + } + + public static long getCutOffTimeStampFromLimit(final String conversationId, + final int maxLimit, final int protocol) { + final DatabaseWrapper db = DataModel.get().getDatabase(); + db.beginTransaction(); + Cursor cursor = null; + Long cutoffTimeStamp = Long.MIN_VALUE; + try { + cursor = db.query(DatabaseHelper.MESSAGES_TABLE, + new String[]{ MessageColumns.RECEIVED_TIMESTAMP }, + MessageColumns.CONVERSATION_ID + "=? AND " + MessageColumns.PROTOCOL + "=?", + new String[]{ conversationId, Integer.toString(protocol) }, null, null, + MessageColumns.RECEIVED_TIMESTAMP + " DESC", null); + if (cursor != null && cursor.getCount() > maxLimit) { + cursor.moveToPosition(maxLimit); + cutoffTimeStamp = cursor.getLong(0); + } + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + if (cursor != null) { + cursor.close(); + } + } + return cutoffTimeStamp; + } } diff --git a/src/com/android/messaging/datamodel/action/InsertNewMessageAction.java b/src/com/android/messaging/datamodel/action/InsertNewMessageAction.java index 2567ca9..6f8dd82 100644 --- a/src/com/android/messaging/datamodel/action/InsertNewMessageAction.java +++ b/src/com/android/messaging/datamodel/action/InsertNewMessageAction.java @@ -334,6 +334,7 @@ public class InsertNewMessageAction extends Action implements Parcelable { } MessagingContentProvider.notifyMessagesChanged(conversationId); MessagingContentProvider.notifyPartsChanged(); + MessageRecyclerAction.deleteMessagesOverLimit(conversationId, MessageData.PROTOCOL_SMS); } else { // Ignore error as we only really care about the individual messages? LogUtil.e(TAG, @@ -412,6 +413,7 @@ public class InsertNewMessageAction extends Action implements Parcelable { } MessagingContentProvider.notifyMessagesChanged(conversationId); MessagingContentProvider.notifyPartsChanged(); + MessageRecyclerAction.deleteMessagesOverLimit(conversationId, MessageData.PROTOCOL_SMS); } else { LogUtil.e(TAG, "InsertNewMessageAction: No uri for SMS inserted into telephony DB"); } @@ -452,7 +454,7 @@ public class InsertNewMessageAction extends Action implements Parcelable { } MessagingContentProvider.notifyMessagesChanged(conversationId); MessagingContentProvider.notifyPartsChanged(); - + MessageRecyclerAction.deleteMessagesOverLimit(conversationId, MessageData.PROTOCOL_MMS); return message; } diff --git a/src/com/android/messaging/datamodel/action/MessageRecyclerAction.java b/src/com/android/messaging/datamodel/action/MessageRecyclerAction.java new file mode 100644 index 0000000..86da6aa --- /dev/null +++ b/src/com/android/messaging/datamodel/action/MessageRecyclerAction.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2016 The CyanogenMod 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.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; +import com.android.messaging.datamodel.BugleDatabaseOperations; +import com.android.messaging.datamodel.DataModel; +import com.android.messaging.datamodel.DatabaseWrapper; +import com.android.messaging.datamodel.MessagingContentProvider; +import com.android.messaging.datamodel.data.MessageData; +import com.android.messaging.sms.MmsUtils; +import com.android.messaging.util.LogUtil; +import com.cyanogenmod.messaging.util.PrefsUtils; + +/* + * Action used to delete a messages based on limit specified by user/config. + */ + + +public class MessageRecyclerAction extends Action implements Parcelable { + private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG; + + public static void deleteMessagesOverLimit(final String conversationId, int protocol) { + + if (!PrefsUtils.isAutoDeleteEnabled() || (protocol != MessageData.PROTOCOL_SMS + && protocol != MessageData.PROTOCOL_MMS)) { + return; + } + + int cutOffLimit = PrefsUtils.getMessagesPerThreadLimitByProtocol(protocol); + long cutOffTimeStampFromLimit = BugleDatabaseOperations. + getCutOffTimeStampFromLimit(conversationId, cutOffLimit, MessageData.PROTOCOL_SMS); + + if (cutOffTimeStampFromLimit > Long.MIN_VALUE) { + deleteMessages(conversationId, protocol, cutOffTimeStampFromLimit); + } + } + + public static void deleteMessages(final String conversationId, + final int protocol, final long cutOffTimeStamp) { + final MessageRecyclerAction action = + new MessageRecyclerAction(conversationId, protocol, cutOffTimeStamp); + action.start(); + } + + private static final String KEY_CONVERSATION_ID = "key_conversation_id"; + private static final String KEY_PROTOCOL = "key_protocol"; + private static final String KEY_CUTOFF_TIMESTAMP = "key_cutoff_timestamp"; + + private MessageRecyclerAction(final String conversationId, + final int protocol, final long cutOffTimeStamp) { + super(); + actionParameters.putString(KEY_CONVERSATION_ID, conversationId); + actionParameters.putInt(KEY_PROTOCOL, protocol); + actionParameters.putLong(KEY_CUTOFF_TIMESTAMP, cutOffTimeStamp); + } + + @Override + protected Bundle doBackgroundWork() { + final DatabaseWrapper db = DataModel.get().getDatabase(); + + final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID); + final int protocol = actionParameters.getInt(KEY_PROTOCOL); + final long cutOffTimeStamp = actionParameters.getLong(KEY_CUTOFF_TIMESTAMP); + + if (!TextUtils.isEmpty(conversationId)) { + // Delete from local DB + BugleDatabaseOperations. + deleteConversationByProtocol(db, conversationId, cutOffTimeStamp, protocol); + + // We may have changed the conversation list + MessagingContentProvider.notifyMessagesChanged(conversationId); + MessagingContentProvider.notifyConversationListChanged(); + + int count = MmsUtils.deleteMessagesOlderThanByProtocol(cutOffTimeStamp, protocol); + if (count > 0) { + LogUtil.i(TAG, "MessageRecyclerAction: Deleted telephony messages " + + count); + } else { + LogUtil.w(TAG, "MessageRecyclerAction: Could not delete message from telephony"); + } + } + return null; + } + + @Override + protected Object executeAction() { + requestBackgroundWork(); + return null; + } + + private MessageRecyclerAction(final Parcel in) { + super(in); + } + + public static final Creator<MessageRecyclerAction> CREATOR + = new Creator<MessageRecyclerAction>() { + @Override + public MessageRecyclerAction createFromParcel(final Parcel in) { + return new MessageRecyclerAction(in); + } + + @Override + public MessageRecyclerAction[] newArray(final int size) { + return new MessageRecyclerAction[size]; + } + }; + + @Override + public void writeToParcel(final Parcel parcel, final int flags) { + writeActionToParcel(parcel, flags); + } +} diff --git a/src/com/android/messaging/datamodel/action/ProcessDownloadedMmsAction.java b/src/com/android/messaging/datamodel/action/ProcessDownloadedMmsAction.java index 757ea05..93f738f 100644 --- a/src/com/android/messaging/datamodel/action/ProcessDownloadedMmsAction.java +++ b/src/com/android/messaging/datamodel/action/ProcessDownloadedMmsAction.java @@ -545,6 +545,7 @@ public class ProcessDownloadedMmsAction extends Action { } MessagingContentProvider.notifyMessagesChanged(notificationConversationId); MessagingContentProvider.notifyPartsChanged(); + MessageRecyclerAction.deleteMessagesOverLimit(conversationId, MessageData.PROTOCOL_MMS); return message; } diff --git a/src/com/android/messaging/datamodel/action/ReceiveMmsMessageAction.java b/src/com/android/messaging/datamodel/action/ReceiveMmsMessageAction.java index 6794b17..4ebc8b4 100644 --- a/src/com/android/messaging/datamodel/action/ReceiveMmsMessageAction.java +++ b/src/com/android/messaging/datamodel/action/ReceiveMmsMessageAction.java @@ -134,7 +134,8 @@ public class ReceiveMmsMessageAction extends Action implements Parcelable { if (!autoDownload) { MessagingContentProvider.notifyMessagesChanged(message.getConversationId()); MessagingContentProvider.notifyPartsChanged(); - + MessageRecyclerAction.deleteMessagesOverLimit(conversationId, + MessageData.PROTOCOL_MMS); // Show a notification to let the user know a new message has arrived BugleNotifications.update(false/*silent*/, conversationId, BugleNotifications.UPDATE_ALL); diff --git a/src/com/android/messaging/datamodel/action/ReceiveSmsMessageAction.java b/src/com/android/messaging/datamodel/action/ReceiveSmsMessageAction.java index 5ffb35d..b8c97b9 100644 --- a/src/com/android/messaging/datamodel/action/ReceiveSmsMessageAction.java +++ b/src/com/android/messaging/datamodel/action/ReceiveSmsMessageAction.java @@ -170,7 +170,7 @@ public class ReceiveSmsMessageAction extends Action implements Parcelable { MessagingContentProvider.notifyMessagesChanged(conversationId); MessagingContentProvider.notifyPartsChanged(); - + MessageRecyclerAction.deleteMessagesOverLimit(conversationId, MessageData.PROTOCOL_SMS); return message; } diff --git a/src/com/android/messaging/datamodel/action/SyncMessageBatch.java b/src/com/android/messaging/datamodel/action/SyncMessageBatch.java index 972d691..87e7448 100644 --- a/src/com/android/messaging/datamodel/action/SyncMessageBatch.java +++ b/src/com/android/messaging/datamodel/action/SyncMessageBatch.java @@ -192,6 +192,7 @@ class SyncMessageBatch { + message.getReceivedTimeStamp()); } + MessageRecyclerAction.deleteMessagesOverLimit(conversationId, MessageData.PROTOCOL_SMS); // Keep track of updated conversation for later updating the conversation snippet, etc. mConversationsToUpdate.add(conversationId); } @@ -281,7 +282,7 @@ class SyncMessageBatch { + " for MMS " + message.getSmsMessageUri() + " received at " + message.getReceivedTimeStamp()); } - + MessageRecyclerAction.deleteMessagesOverLimit(conversationId, MessageData.PROTOCOL_MMS); // Keep track of updated conversation for later updating the conversation snippet, etc. mConversationsToUpdate.add(conversationId); } diff --git a/src/com/android/messaging/sms/MmsConfig.java b/src/com/android/messaging/sms/MmsConfig.java index f13d785..56898cf 100755 --- a/src/com/android/messaging/sms/MmsConfig.java +++ b/src/com/android/messaging/sms/MmsConfig.java @@ -90,6 +90,12 @@ public class MmsConfig { sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_HTTP_PARAMS, KEY_TYPE_STRING); sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_EMAIL_GATEWAY_NUMBER, KEY_TYPE_STRING); sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_NAI_SUFFIX, KEY_TYPE_STRING); + sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MIN_MESSAGE_COUNT_PER_THREAD, + KEY_TYPE_INT); + sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SMS_MESSAGES_PER_THREAD, KEY_TYPE_INT); + sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MMS_MESSAGES_PER_THREAD, KEY_TYPE_INT); + sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_COUNT_PER_THREAD, + KEY_TYPE_INT); } // A map that stores all MmsConfigs, one per active subscription. For pre-LMSim, this will @@ -187,6 +193,36 @@ public class MmsConfig { CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_SIZE_DEFAULT); } + public static int getMaxOfTheConfigValues(String configName, int defaultValue) { + int max = 0; + for (MmsConfig config : sSubIdToMmsConfigMap.values()) { + max = Math.max(max, config.mValues.getInt(configName, 0)); + } + return (max > 0) ? max : defaultValue; + } + + public static int getMinMessageCountPerThread() { + return getMaxOfTheConfigValues( + CarrierConfigValuesLoader.CONFIG_MIN_MESSAGE_COUNT_PER_THREAD, + CarrierConfigValuesLoader.CONFIG_MIN_MESSAGE_COUNT_PER_THREAD_DEFAULT); + } + + public static int getMaxMessageCountPerThread() { + return getMaxOfTheConfigValues( + CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_COUNT_PER_THREAD, + CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_COUNT_PER_THREAD_DEFAULT); + } + + public static int getSMSMessagesPerThread() { + return getMaxOfTheConfigValues(CarrierConfigValuesLoader.CONFIG_SMS_MESSAGES_PER_THREAD, + CarrierConfigValuesLoader.CONFIG_SMS_MESSAGES_PER_THREAD_DEFAULT); + } + + public static int getMMSMessagesPerThread() { + return getMaxOfTheConfigValues(CarrierConfigValuesLoader.CONFIG_MMS_MESSAGES_PER_THREAD, + CarrierConfigValuesLoader.CONFIG_MMS_MESSAGES_PER_THREAD_DEFAULT); + } + /** * Return the largest MaxMessageSize for any subid */ diff --git a/src/com/android/messaging/sms/MmsUtils.java b/src/com/android/messaging/sms/MmsUtils.java index c91747b..1fd811f 100644 --- a/src/com/android/messaging/sms/MmsUtils.java +++ b/src/com/android/messaging/sms/MmsUtils.java @@ -1386,6 +1386,39 @@ public class MmsUtils { return deleted; } + public static int deleteMessagesOlderThanByProtocol(final long cutOffTimestampInMillis, + final int protocol) { + Uri uri; + String selectionSql; + String dateField; + + switch (protocol) { + case MessageData.PROTOCOL_SMS: + uri = Sms.CONTENT_URI; + selectionSql = getSmsTypeSelectionSql(); + dateField = Sms.DATE; + break; + case MessageData.PROTOCOL_MMS: + uri = Mms.CONTENT_URI; + selectionSql = getMmsTypeSelectionSql(); + dateField = Mms.DATE; + break; + default: + return 0; + } + final ContentResolver resolver = + Factory.get().getApplicationContext().getContentResolver(); + final String selection = String.format( + Locale.US, + "%s AND (%s<=%d)", + selectionSql, + dateField, + cutOffTimestampInMillis); + int deleted = resolver.delete(uri, selection, null); + + return deleted; + } + /** * Update the read status of SMS/MMS messages by thread and timestamp * diff --git a/src/com/android/messaging/ui/NumberPickerDialog.java b/src/com/android/messaging/ui/NumberPickerDialog.java new file mode 100644 index 0000000..755bc81 --- /dev/null +++ b/src/com/android/messaging/ui/NumberPickerDialog.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2007 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; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.NumberPicker; +import android.widget.TextView; + +import com.android.messaging.R; +/** + * A dialog that prompts the user for the message deletion limits. + */ +public class NumberPickerDialog extends AlertDialog implements OnClickListener { + private static final String NUMBER = "number"; + + /** + * The callback interface used to indicate the user is done filling in + * the time (they clicked on the 'Set' button). + */ + public interface OnNumberSetListener { + + /** + * @param number The number that was set. + */ + void onNumberSet(int number); + } + + private final NumberPicker mNumberPicker; + private final OnNumberSetListener mCallback; + + /** + * @param context Parent. + * @param callBack How parent is notified. + * @param number The initial number. + */ + public NumberPickerDialog(Context context, + OnNumberSetListener callBack, + int number, + int rangeMin, + int rangeMax, + int title, + int header) { + this(context, callBack, number, rangeMin, rangeMax, title, header, 0); + } + + /** + * @param context Parent. + * @param callBack How parent is notified. + * @param number The initial number. + */ + public NumberPickerDialog(Context context, + OnNumberSetListener callBack, + int number, + int rangeMin, + int rangeMax, + int title, + int header, + int unit) { + super(context); + mCallback = callBack; + + setTitle(title); + + setButton(DialogInterface.BUTTON_POSITIVE, context.getText(R.string.set), this); + setButton(DialogInterface.BUTTON_NEGATIVE, context.getText(R.string.no), + (OnClickListener) null); + + LayoutInflater inflater = + (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View view = inflater.inflate(R.layout.number_picker_dialog, null); + setView(view); + mNumberPicker = (NumberPicker) view.findViewById(R.id.number_picker); + + TextView headerView = (TextView) view.findViewById(R.id.header); + if (header != 0) { + headerView.setText(header); + headerView.setVisibility(View.VISIBLE); + } else { + headerView.setVisibility(View.GONE); + } + TextView unitView = (TextView) view.findViewById(R.id.unit); + if (unit != 0) { + unitView.setText(unit); + unitView.setVisibility(View.VISIBLE); + } else { + unitView.setVisibility(View.GONE); + } + + // initialize state + mNumberPicker.setMinValue(rangeMin); + mNumberPicker.setMaxValue(rangeMax); + mNumberPicker.setValue(number); + mNumberPicker.setOnLongPressUpdateInterval(100); // make the repeat rate three times as fast + // as normal since the range is so large. + mNumberPicker.setWrapSelectorWheel(false); // don't wrap from min->max + } + + public void onClick(DialogInterface dialog, int which) { + if (mCallback != null) { + mNumberPicker.clearFocus(); + mCallback.onNumberSet(mNumberPicker.getValue()); + dialog.dismiss(); + } + } + + @Override + public Bundle onSaveInstanceState() { + Bundle state = super.onSaveInstanceState(); + state.putInt(NUMBER, mNumberPicker.getValue()); + return state; + } + + @Override + public void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + int number = savedInstanceState.getInt(NUMBER); + mNumberPicker.setValue(number); + } +} diff --git a/src/com/android/messaging/ui/appsettings/ApplicationSettingsActivity.java b/src/com/android/messaging/ui/appsettings/ApplicationSettingsActivity.java index 81993a2..b91cc6c 100644 --- a/src/com/android/messaging/ui/appsettings/ApplicationSettingsActivity.java +++ b/src/com/android/messaging/ui/appsettings/ApplicationSettingsActivity.java @@ -38,13 +38,16 @@ import android.view.Menu; import android.view.MenuItem; import com.android.messaging.R; +import com.android.messaging.sms.MmsConfig; import com.android.messaging.ui.BugleActionBarActivity; import com.android.messaging.ui.LicenseActivity; +import com.android.messaging.ui.NumberPickerDialog; import com.android.messaging.ui.UIIntents; import com.android.messaging.util.BuglePrefs; import com.android.messaging.util.DebugUtils; import com.android.messaging.util.OsUtil; import com.android.messaging.util.PhoneUtils; +import com.cyanogenmod.messaging.util.PrefsUtils; public class ApplicationSettingsActivity extends BugleActionBarActivity { @Override @@ -104,6 +107,8 @@ public class ApplicationSettingsActivity extends BugleActionBarActivity { private ListPreference mSmsValidityPref; private ListPreference mSmsValidityCard1Pref; private ListPreference mSmsValidityCard2Pref; + private Preference mSmsLimitPref; + private Preference mMmsLimitPref; public ApplicationSettingsFragment() { @@ -132,6 +137,8 @@ public class ApplicationSettingsActivity extends BugleActionBarActivity { mSmsValidityPref = (ListPreference) findPreference("pref_key_sms_validity_period"); mSmsValidityCard1Pref = (ListPreference) findPreference("pref_key_sms_validity_period_slot1"); mSmsValidityCard2Pref = (ListPreference) findPreference("pref_key_sms_validity_period_slot2"); + mSmsLimitPref = findPreference("sms_delete_limit_pref_key"); + mMmsLimitPref = findPreference("mms_delete_limit_pref_key"); if (getResources().getBoolean(R.bool.config_sms_validity)) { if (PhoneUtils.getDefault().isMultiSimEnabledMms()) { @@ -172,6 +179,8 @@ public class ApplicationSettingsActivity extends BugleActionBarActivity { // the parent SettingsActivity. getPreferenceScreen().removePreference(advancedScreen); } + setSmsDisplayLimit(); + setMmsDisplayLimit(); } @Override @@ -180,6 +189,28 @@ public class ApplicationSettingsActivity extends BugleActionBarActivity { if (preference.getKey() == mSmsDisabledPrefKey || preference.getKey() == mSmsEnabledPrefKey) { mIsSmsPreferenceClicked = true; + } else if (getActivity() != null && + preference.getKey().equals(mSmsLimitPref.getKey())) { + + new NumberPickerDialog(getActivity(), + mSmsLimitListener, + PrefsUtils.getSMSMessagesPerThreadLimit(), + MmsConfig.getMinMessageCountPerThread(), + MmsConfig.getMaxMessageCountPerThread(), + R.string.sms_delete_pref_title, + R.string.pref_messages_to_save).show(); + + } else if(getActivity() != null && + preference.getKey().equals(mMmsLimitPref.getKey())) { + + new NumberPickerDialog(getActivity(), + mMmsLimitListener, + PrefsUtils.getMMSMessagesPerThreadLimit(), + MmsConfig.getMinMessageCountPerThread(), + MmsConfig.getMaxMessageCountPerThread(), + R.string.mms_delete_pref_title, + R.string.pref_messages_to_save).show(); + } return super.onPreferenceTreeClick(preferenceScreen, preference); } @@ -286,5 +317,33 @@ public class ApplicationSettingsActivity extends BugleActionBarActivity { getPreferenceScreen().getSharedPreferences() .unregisterOnSharedPreferenceChangeListener(this); } + + private void setSmsDisplayLimit() { + mSmsLimitPref.setSummary( + getString(R.string.pref_summary_delete_limit, + PrefsUtils.getSMSMessagesPerThreadLimit())); + } + + private void setMmsDisplayLimit() { + mMmsLimitPref.setSummary( + getString(R.string.pref_summary_delete_limit, + PrefsUtils.getMMSMessagesPerThreadLimit())); + } + + NumberPickerDialog.OnNumberSetListener mSmsLimitListener = + new NumberPickerDialog.OnNumberSetListener() { + public void onNumberSet(int limit) { + PrefsUtils.setSMSMessagesPerThreadLimit(limit); + setSmsDisplayLimit(); + } + }; + + NumberPickerDialog.OnNumberSetListener mMmsLimitListener = + new NumberPickerDialog.OnNumberSetListener() { + public void onNumberSet(int limit) { + PrefsUtils.setMMSMessagesPerThreadLimit(limit); + setMmsDisplayLimit(); + } + }; } } diff --git a/src/com/cyanogenmod/messaging/util/PrefsUtils.java b/src/com/cyanogenmod/messaging/util/PrefsUtils.java index 4afbb6d..7af4c06 100644 --- a/src/com/cyanogenmod/messaging/util/PrefsUtils.java +++ b/src/com/cyanogenmod/messaging/util/PrefsUtils.java @@ -17,13 +17,14 @@ package com.cyanogenmod.messaging.util; import android.content.Context; -import android.content.SharedPreferences; - import com.android.messaging.Factory; import com.android.messaging.R; +import com.android.messaging.datamodel.data.MessageData; +import com.android.messaging.sms.MmsConfig; import com.android.messaging.util.BuglePrefs; import com.android.messaging.util.UnicodeFilter; import com.android.messaging.util.PhoneUtils; +import java.lang.IllegalArgumentException; public class PrefsUtils { @@ -32,6 +33,13 @@ public class PrefsUtils { public static final String QM_CLOSE_ALL_ENABLED = "pref_key_close_all"; public static final String SHOW_EMOTICONS_ENABLED = "pref_show_emoticons"; + //Storage Limits + public static final String PREF_STORAGE_AUTO_DELETE = "auto_delete_pref_key"; + public static final String PREF_SMS_MESSAGES_PER_THREAD = "sms_delete_limit_pref_key"; + public static final String PREF_MMS_MESSAGES_PER_THREAD = "mms_delete_limit_pref_key"; + + public static final boolean PREF_STORAGE_AUTO_DELETE_DEFAULT = false; + private PrefsUtils() { //Don't instantiate } @@ -100,4 +108,40 @@ public class PrefsUtils { return (validityPeriod == null) ? -1 : Integer.parseInt(validityPeriod); } + public static boolean isAutoDeleteEnabled() { + final BuglePrefs prefs = BuglePrefs.getApplicationPrefs(); + return prefs.getBoolean(PREF_STORAGE_AUTO_DELETE, PREF_STORAGE_AUTO_DELETE_DEFAULT); + } + + public static void setSMSMessagesPerThreadLimit(int limit) { + final BuglePrefs prefs = BuglePrefs.getApplicationPrefs(); + prefs.putInt(PREF_SMS_MESSAGES_PER_THREAD, limit); + } + + public static void setMMSMessagesPerThreadLimit(int limit) { + final BuglePrefs prefs = BuglePrefs.getApplicationPrefs(); + prefs.putInt(PREF_MMS_MESSAGES_PER_THREAD, limit); + } + + public static int getSMSMessagesPerThreadLimit() { + final BuglePrefs prefs = BuglePrefs.getApplicationPrefs(); + return prefs.getInt(PREF_SMS_MESSAGES_PER_THREAD, MmsConfig.getSMSMessagesPerThread()); + } + + public static int getMMSMessagesPerThreadLimit() { + final BuglePrefs prefs = BuglePrefs.getApplicationPrefs(); + return prefs.getInt(PREF_MMS_MESSAGES_PER_THREAD, MmsConfig.getMMSMessagesPerThread()); + } + + public static int getMessagesPerThreadLimitByProtocol(int protocol) { + if(protocol == MessageData.PROTOCOL_SMS) { + return getSMSMessagesPerThreadLimit(); + } else if(protocol == MessageData.PROTOCOL_MMS) { + return getMMSMessagesPerThreadLimit(); + } + + throw new IllegalArgumentException("Invalid Protocol protocol =" + + Integer.toString(protocol)); + } + } |