/*
* Copyright (C) 2011 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.internal.telephony;
import android.content.ContentResolver;
import android.provider.Settings;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Implement the per-application based SMS control, which limits the number of
* SMS/MMS messages an app can send in the checking period.
*
* This code was formerly part of {@link SMSDispatcher}, and has been moved
* into a separate class to support instantiation of multiple SMSDispatchers on
* dual-mode devices that require support for both 3GPP and 3GPP2 format messages.
*/
publicclassSmsUsageMonitor{
privatestaticfinalString TAG ="SmsStorageMonitor";
/** Default checking period for SMS sent without user permission. */
privatestaticfinalint DEFAULT_SMS_CHECK_PERIOD =3600000;
/** Default number of SMS sent in checking period without user permission. */
privatestaticfinalint DEFAULT_SMS_MAX_COUNT =100;
privatefinalint mCheckPeriod;
privatefinalint mMaxAllowed;
privatefinalHashMap<String,ArrayList<Long>> mSmsStamp =
newHashMap<String,ArrayList<Long>>();
/**
* Create SMS usage monitor.
* @param resolver the ContentResolver to use to load from secure settings
*/
publicSmsUsageMonitor(ContentResolver resolver){
mMaxAllowed =Settings.Secure.getInt(resolver,
Settings.Secure.SMS_OUTGOING_CHECK_MAX_COUNT,
DEFAULT_SMS_MAX_COUNT);
mCheckPeriod =Settings.Secure.getInt(resolver,
Settings.Secure.SMS_OUTGOING_CHECK_INTERVAL_MS,
DEFAULT_SMS_CHECK_PERIOD);
}
/** Clear the SMS application list for disposal. */
void dispose(){
mSmsStamp.clear();
}
/**
* Check to see if an application is allowed to send new SMS messages.
*
* @param appName the application sending sms
* @param smsWaiting the number of new messages desired to send
* @return true if application is allowed to send the requested number
* of new sms messages
*/
publicboolean check(String appName,int smsWaiting){
synchronized(mSmsStamp){
removeExpiredTimestamps();
ArrayList<Long> sentList = mSmsStamp.get(appName);
if(sentList ==null){
sentList =newArrayList<Long>();
mSmsStamp.put(appName, sentList);
}
return isUnderLimit(sentList, smsWaiting);
}
}
/**
* Remove keys containing only old timestamps. This can happen if an SMS app is used
* to send messages and then uninstalled.
*/
privatevoid removeExpiredTimestamps(){
long beginCheckPeriod =System.currentTimeMillis()- mCheckPeriod;
synchronized(mSmsStamp){
Iterator<Map.Entry<String,ArrayList<Long>>> iter = mSmsStamp.entrySet().iterator();
while(iter.hasNext()){
Map.Entry<String,ArrayList<Long>> entry = iter.next();
ArrayList<Long> oldList = entry.getValue();
if(oldList.isEmpty()|| oldList.get(oldList.size()-1)< beginCheckPeriod){
iter.remove();
}
}
}
}
privateboolean isUnderLimit(ArrayList<Long> sent,int smsWaiting){
Long ct =System.currentTimeMillis();
long beginCheckPeriod = ct - mCheckPeriod;
Log.d(TAG,"SMS send size="+ sent.size()+" time="+ ct);
while(!sent.isEmpty()&& sent.get(0)< beginCheckPeriod){
sent.remove(0);
}
if((sent.size()+ smsWaiting)<= mMaxAllowed){
for(int i =0; i < smsWaiting; i++){
sent.add(ct);
}
returntrue;
}
returnfalse;
}
}