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.database.sqlite.SqliteWrapper; 21 22 import android.content.BroadcastReceiver; 23 import android.content.ContentValues; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.database.Cursor; 28 import android.provider.Telephony.Mms.Rate; 29 import android.util.Log; 30 31 public class RateController { 32 private static final String TAG = "RateController"; 33 private static final boolean DEBUG = false; 34 private static final boolean LOCAL_LOGV = false; 35 36 private static final int RATE_LIMIT = 100; 37 private static final long ONE_HOUR = 1000 * 60 * 60; 38 39 private static final int NO_ANSWER = 0; 40 private static final int ANSWER_YES = 1; 41 private static final int ANSWER_NO = 2; 42 43 public static final int ANSWER_TIMEOUT = 20000; 44 public static final String RATE_LIMIT_SURPASSED_ACTION = 45 "com.android.mms.RATE_LIMIT_SURPASSED"; 46 public static final String RATE_LIMIT_CONFIRMED_ACTION = 47 "com.android.mms.RATE_LIMIT_CONFIRMED"; 48 49 private static RateController sInstance; 50 private static boolean sMutexLock; 51 52 private final Context mContext; 53 private int mAnswer; 54 55 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 56 @Override 57 public void onReceive(Context context, Intent intent) { 58 if (LOCAL_LOGV) { 59 Log.v(TAG, "Intent received: " + intent); 60 } 61 62 if (RATE_LIMIT_CONFIRMED_ACTION.equals(intent.getAction())) { 63 synchronized (this) { 64 mAnswer = intent.getBooleanExtra("answer", false) 65 ? ANSWER_YES : ANSWER_NO; 66 notifyAll(); 67 } 68 } 69 } 70 }; 71 72 private RateController(Context context) { 73 mContext = context; 74 } 75 76 public static void init(Context context) { 77 if (LOCAL_LOGV) { 78 Log.v(TAG, "RateController.init()"); 79 } 80 81 if (sInstance != null) { 82 Log.w(TAG, "Already initialized."); 83 } 84 sInstance = new RateController(context); 85 } 86 87 public static RateController getInstance() { 88 if (sInstance == null) { 89 throw new IllegalStateException("Uninitialized."); 90 } 91 return sInstance; 92 } 93 94 public final void update() { 95 ContentValues values = new ContentValues(1); 96 values.put(Rate.SENT_TIME, System.currentTimeMillis()); 97 SqliteWrapper.insert(mContext, mContext.getContentResolver(), 98 Rate.CONTENT_URI, values); 99 } 100 101 public final boolean isLimitSurpassed() { 102 long oneHourAgo = System.currentTimeMillis() - ONE_HOUR; 103 Cursor c = SqliteWrapper.query(mContext, mContext.getContentResolver(), 104 Rate.CONTENT_URI, new String[] { "COUNT(*) AS rate" }, 105 Rate.SENT_TIME + ">" + oneHourAgo, null, null); 106 if (c != null) { 107 try { 108 if (c.moveToFirst()) { 109 return c.getInt(0) >= RATE_LIMIT; 110 } 111 } finally { 112 c.close(); 113 } 114 } 115 return false; 116 } 117 118 synchronized public boolean isAllowedByUser() { 119 while (sMutexLock) { 120 try { 121 wait(); 122 } catch (InterruptedException _) { 123 // Ignore it. 124 } 125 } 126 sMutexLock = true; 127 128 mContext.registerReceiver(mBroadcastReceiver, 129 new IntentFilter(RATE_LIMIT_CONFIRMED_ACTION)); 130 131 mAnswer = NO_ANSWER; 132 try { 133 Intent intent = new Intent(RATE_LIMIT_SURPASSED_ACTION); 134 // Using NEW_TASK here is necessary because we're calling 135 // startActivity from outside an activity. 136 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 137 mContext.startActivity(intent); 138 return waitForAnswer() == ANSWER_YES; 139 } finally { 140 mContext.unregisterReceiver(mBroadcastReceiver); 141 sMutexLock = false; 142 notifyAll(); 143 } 144 } 145 146 synchronized private int waitForAnswer() { 147 for (int t = 0; (mAnswer == NO_ANSWER) && (t < ANSWER_TIMEOUT); t += 1000) { 148 try { 149 if (LOCAL_LOGV) { 150 Log.v(TAG, "Waiting for answer..." + t / 1000); 151 } 152 wait(1000L); 153 } catch (InterruptedException _) { 154 // Ignore it. 155 } 156 } 157 return mAnswer; 158 } 159 } 160