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.Config;
     30 import android.util.Log;
     31 
     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;
     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         }
     85         sInstance = new RateController(context);
     86     }
     87 
     88     public static RateController getInstance() {
     89         if (sInstance == null) {
     90             throw new IllegalStateException("Uninitialized.");
     91         }
     92         return sInstance;
     93     }
     94 
     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);
    100     }
    101 
    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);
    107         if (c != null) {
    108             try {
    109                 if (c.moveToFirst()) {
    110                     return c.getInt(0) >= RATE_LIMIT;
    111                 }
    112             } finally {
    113                 c.close();
    114             }
    115         }
    116         return false;
    117     }
    118 
    119     synchronized public boolean isAllowedByUser() {
    120         while (sMutexLock) {
    121             try {
    122                 wait();
    123             } catch (InterruptedException _) {
    124                  // Ignore it.
    125             }
    126         }
    127         sMutexLock = true;
    128 
    129         mContext.registerReceiver(mBroadcastReceiver,
    130                 new IntentFilter(RATE_LIMIT_CONFIRMED_ACTION));
    131 
    132         mAnswer = NO_ANSWER;
    133         try {
    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;
    140         } finally {
    141             mContext.unregisterReceiver(mBroadcastReceiver);
    142             sMutexLock = false;
    143             notifyAll();
    144         }
    145     }
    146 
    147     synchronized private int waitForAnswer() {
    148         for (int t = 0; (mAnswer == NO_ANSWER) && (t < ANSWER_TIMEOUT); t += 1000) {
    149             try {
    150                 if (LOCAL_LOGV) {
    151                     Log.v(TAG, "Waiting for answer..." + t / 1000);
    152                 }
    153                 wait(1000L);
    154             } catch (InterruptedException _) {
    155                  // Ignore it.
    156             }
    157         }
    158         return mAnswer;
    159     }
    160 }
    161