1 /* 2 * Copyright (C) 2008 Esmertec AG. 3 * Copyright (C) 2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.mms.util; 19 20 import android.content.BroadcastReceiver; 21 import android.content.ContentValues; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.database.Cursor; 26 import android.database.sqlite.SqliteWrapper; 27 import android.provider.Telephony.Mms.Rate; 28 import android.util.Log; 29 30 public class RateController { 31 private static final String TAG = "RateController"; 32 private static final boolean DEBUG = false; 33 private static final boolean LOCAL_LOGV = false; 34 35 private static final int RATE_LIMIT = 100; 36 private static final long ONE_HOUR = 1000 * 60 * 60; 37 38 private static final int NO_ANSWER = 0; 39 private static final int ANSWER_YES = 1; 40 private static final int ANSWER_NO = 2; 41 42 public static final int ANSWER_TIMEOUT = 20000; 43 public static final String RATE_LIMIT_SURPASSED_ACTION = 44 "com.android.mms.RATE_LIMIT_SURPASSED"; 45 public static final String RATE_LIMIT_CONFIRMED_ACTION = 46 "com.android.mms.RATE_LIMIT_CONFIRMED"; 47 48 private static RateController sInstance; 49 private static boolean sMutexLock; 50 51 private final Context mContext; 52 private int mAnswer; 53 54 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 55 @Override 56 public void onReceive(Context context, Intent intent) { 57 if (LOCAL_LOGV) { 58 Log.v(TAG, "Intent received: " + intent); 59 } 60 61 if (RATE_LIMIT_CONFIRMED_ACTION.equals(intent.getAction())) { 62 synchronized (this) { 63 mAnswer = intent.getBooleanExtra("answer", false) 64 ? ANSWER_YES : ANSWER_NO; 65 notifyAll(); 66 } 67 } 68 } 69 }; 70 71 private RateController(Context context) { 72 mContext = context; 73 } 74 75 public static void init(Context context) { 76 if (LOCAL_LOGV) { 77 Log.v(TAG, "RateController.init()"); 78 } 79 80 if (sInstance != null) { 81 Log.w(TAG, "Already initialized."); 82 } 83 sInstance = new RateController(context); 84 } 85 86 public static RateController getInstance() { 87 if (sInstance == null) { 88 throw new IllegalStateException("Uninitialized."); 89 } 90 return sInstance; 91 } 92 93 public final void update() { 94 ContentValues values = new ContentValues(1); 95 values.put(Rate.SENT_TIME, System.currentTimeMillis()); 96 SqliteWrapper.insert(mContext, mContext.getContentResolver(), 97 Rate.CONTENT_URI, values); 98 } 99 100 public final boolean isLimitSurpassed() { 101 long oneHourAgo = System.currentTimeMillis() - ONE_HOUR; 102 Cursor c = SqliteWrapper.query(mContext, mContext.getContentResolver(), 103 Rate.CONTENT_URI, new String[] { "COUNT(*) AS rate" }, 104 Rate.SENT_TIME + ">" + oneHourAgo, null, null); 105 if (c != null) { 106 try { 107 if (c.moveToFirst()) { 108 return c.getInt(0) >= RATE_LIMIT; 109 } 110 } finally { 111 c.close(); 112 } 113 } 114 return false; 115 } 116 117 synchronized public boolean isAllowedByUser() { 118 while (sMutexLock) { 119 try { 120 wait(); 121 } catch (InterruptedException _) { 122 // Ignore it. 123 } 124 } 125 sMutexLock = true; 126 127 mContext.registerReceiver(mBroadcastReceiver, 128 new IntentFilter(RATE_LIMIT_CONFIRMED_ACTION)); 129 130 mAnswer = NO_ANSWER; 131 try { 132 Intent intent = new Intent(RATE_LIMIT_SURPASSED_ACTION); 133 // Using NEW_TASK here is necessary because we're calling 134 // startActivity from outside an activity. 135 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 136 mContext.startActivity(intent); 137 return waitForAnswer() == ANSWER_YES; 138 } finally { 139 mContext.unregisterReceiver(mBroadcastReceiver); 140 sMutexLock = false; 141 notifyAll(); 142 } 143 } 144 145 synchronized private int waitForAnswer() { 146 for (int t = 0; (mAnswer == NO_ANSWER) && (t < ANSWER_TIMEOUT); t += 1000) { 147 try { 148 if (LOCAL_LOGV) { 149 Log.v(TAG, "Waiting for answer..." + t / 1000); 150 } 151 wait(1000L); 152 } catch (InterruptedException _) { 153 // Ignore it. 154 } 155 } 156 return mAnswer; 157 } 158 } 159