2 * Copyright (C) 2008 Esmertec AG.
3 * Copyright (C) 2008 The Android Open Source Project
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package com.android.mms.util;
20 import android.database.sqlite.SqliteWrapper;
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.Config;
30 import android.util.Log;
32 public class RateController {
33 private static final String TAG = "RateController";
34 private static final boolean DEBUG = false;
35 private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
37 private static final int RATE_LIMIT = 100;
38 private static final long ONE_HOUR = 1000 * 60 * 60;
40 private static final int NO_ANSWER = 0;
41 private static final int ANSWER_YES = 1;
42 private static final int ANSWER_NO = 2;
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";
50 private static RateController sInstance;
51 private static boolean sMutexLock;
53 private final Context mContext;
56 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
58 public void onReceive(Context context, Intent intent) {
60 Log.v(TAG, "Intent received: " + intent);
63 if (RATE_LIMIT_CONFIRMED_ACTION.equals(intent.getAction())) {
65 mAnswer = intent.getBooleanExtra("answer", false)
66 ? ANSWER_YES : ANSWER_NO;
73 private RateController(Context context) {
77 public static void init(Context context) {
79 Log.v(TAG, "RateController.init()");
82 if (sInstance != null) {
83 Log.w(TAG, "Already initialized.");
85 sInstance = new RateController(context);
88 public static RateController getInstance() {
89 if (sInstance == null) {
90 throw new IllegalStateException("Uninitialized.");
95 public final void update() {
96 ContentValues values = new ContentValues(1);
97 values.put(Rate.SENT_TIME, System.currentTimeMillis());
98 SqliteWrapper.insert(mContext, mContext.getContentResolver(),
99 Rate.CONTENT_URI, values);
102 public final boolean isLimitSurpassed() {
103 long oneHourAgo = System.currentTimeMillis() - ONE_HOUR;
104 Cursor c = SqliteWrapper.query(mContext, mContext.getContentResolver(),
105 Rate.CONTENT_URI, new String[] { "COUNT(*) AS rate" },
106 Rate.SENT_TIME + ">" + oneHourAgo, null, null);
109 if (c.moveToFirst()) {
110 return c.getInt(0) >= RATE_LIMIT;
119 synchronized public boolean isAllowedByUser() {
123 } catch (InterruptedException _) {
129 mContext.registerReceiver(mBroadcastReceiver,
130 new IntentFilter(RATE_LIMIT_CONFIRMED_ACTION));
134 Intent intent = new Intent(RATE_LIMIT_SURPASSED_ACTION);
135 // Using NEW_TASK here is necessary because we're calling
136 // startActivity from outside an activity.
137 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
138 mContext.startActivity(intent);
139 return waitForAnswer() == ANSWER_YES;
141 mContext.unregisterReceiver(mBroadcastReceiver);
147 synchronized private int waitForAnswer() {
148 for (int t = 0; (mAnswer == NO_ANSWER) && (t < ANSWER_TIMEOUT); t += 1000) {
151 Log.v(TAG, "Waiting for answer..." + t / 1000);
154 } catch (InterruptedException _) {