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.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