1b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby/* 2b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * Copyright (C) 2011 The Android Open Source Project 3b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * 4b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * Licensed under the Apache License, Version 2.0 (the "License"); 5b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * you may not use this file except in compliance with the License. 6b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * You may obtain a copy of the License at 7b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * 8b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * http://www.apache.org/licenses/LICENSE-2.0 9b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * 10b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * Unless required by applicable law or agreed to in writing, software 11b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * distributed under the License is distributed on an "AS IS" BASIS, 12b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * See the License for the specific language governing permissions and 14b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * limitations under the License. 15b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby */ 16b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 17b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hambypackage com.android.internal.telephony; 18b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 19b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hambyimport android.content.ContentResolver; 20b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hambyimport android.provider.Settings; 21b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hambyimport android.util.Log; 22b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 23b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hambyimport java.util.ArrayList; 24b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hambyimport java.util.HashMap; 25b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hambyimport java.util.Iterator; 26b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hambyimport java.util.Map; 27b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 28b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby/** 29b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * Implement the per-application based SMS control, which limits the number of 30b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * SMS/MMS messages an app can send in the checking period. 31b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * 32b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * This code was formerly part of {@link SMSDispatcher}, and has been moved 33b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * into a separate class to support instantiation of multiple SMSDispatchers on 34b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * dual-mode devices that require support for both 3GPP and 3GPP2 format messages. 35b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby */ 36b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hambypublic class SmsUsageMonitor { 37b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby private static final String TAG = "SmsStorageMonitor"; 38b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 39b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby /** Default checking period for SMS sent without user permission. */ 40b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby private static final int DEFAULT_SMS_CHECK_PERIOD = 3600000; 41b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 42b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby /** Default number of SMS sent in checking period without user permission. */ 43b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby private static final int DEFAULT_SMS_MAX_COUNT = 100; 44b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 45b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby private final int mCheckPeriod; 46b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby private final int mMaxAllowed; 47b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby private final HashMap<String, ArrayList<Long>> mSmsStamp = 48b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby new HashMap<String, ArrayList<Long>>(); 49b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 50b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby /** 51b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * Create SMS usage monitor. 52b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * @param resolver the ContentResolver to use to load from secure settings 53b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby */ 54b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby public SmsUsageMonitor(ContentResolver resolver) { 55b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby mMaxAllowed = Settings.Secure.getInt(resolver, 56b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby Settings.Secure.SMS_OUTGOING_CHECK_MAX_COUNT, 57b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby DEFAULT_SMS_MAX_COUNT); 58b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 59b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby mCheckPeriod = Settings.Secure.getInt(resolver, 60b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby Settings.Secure.SMS_OUTGOING_CHECK_INTERVAL_MS, 61b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby DEFAULT_SMS_CHECK_PERIOD); 62b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 63b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 64b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby /** Clear the SMS application list for disposal. */ 65b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby void dispose() { 66b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby mSmsStamp.clear(); 67b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 68b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 69b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby /** 70b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * Check to see if an application is allowed to send new SMS messages. 71b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * 72b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * @param appName the application sending sms 73b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * @param smsWaiting the number of new messages desired to send 74b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * @return true if application is allowed to send the requested number 75b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * of new sms messages 76b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby */ 77b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby public boolean check(String appName, int smsWaiting) { 78b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby synchronized (mSmsStamp) { 79b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby removeExpiredTimestamps(); 80b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 81b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby ArrayList<Long> sentList = mSmsStamp.get(appName); 82b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby if (sentList == null) { 83b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby sentList = new ArrayList<Long>(); 84b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby mSmsStamp.put(appName, sentList); 85b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 86b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 87b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby return isUnderLimit(sentList, smsWaiting); 88b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 89b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 90b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 91b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby /** 92b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * Remove keys containing only old timestamps. This can happen if an SMS app is used 93b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby * to send messages and then uninstalled. 94b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby */ 95b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby private void removeExpiredTimestamps() { 96b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby long beginCheckPeriod = System.currentTimeMillis() - mCheckPeriod; 97b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 98b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby synchronized (mSmsStamp) { 99b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby Iterator<Map.Entry<String, ArrayList<Long>>> iter = mSmsStamp.entrySet().iterator(); 100b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby while (iter.hasNext()) { 101b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby Map.Entry<String, ArrayList<Long>> entry = iter.next(); 102b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby ArrayList<Long> oldList = entry.getValue(); 103b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby if (oldList.isEmpty() || oldList.get(oldList.size() - 1) < beginCheckPeriod) { 104b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby iter.remove(); 105b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 106b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 107b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 108b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 109b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 110b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby private boolean isUnderLimit(ArrayList<Long> sent, int smsWaiting) { 111b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby Long ct = System.currentTimeMillis(); 112b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby long beginCheckPeriod = ct - mCheckPeriod; 113b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 114b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby Log.d(TAG, "SMS send size=" + sent.size() + " time=" + ct); 115b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 116b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby while (!sent.isEmpty() && sent.get(0) < beginCheckPeriod) { 117b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby sent.remove(0); 118b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 119b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby 120b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby if ((sent.size() + smsWaiting) <= mMaxAllowed) { 121b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby for (int i = 0; i < smsWaiting; i++ ) { 122b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby sent.add(ct); 123b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 124b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby return true; 125b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 126b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby return false; 127b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby } 128b7945cae5ad0feaad09378d0db77f2b3105e5235Jake Hamby} 129