Home | History | Annotate | Download | only in util
      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