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