• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RateController(Context context)72     private RateController(Context context) {
73         mContext = context;
74     }
75 
init(Context context)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 
getInstance()87     public static RateController getInstance() {
88         if (sInstance == null) {
89             throw new IllegalStateException("Uninitialized.");
90         }
91         return sInstance;
92     }
93 
update()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 
isLimitSurpassed()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 
isAllowedByUser()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 
waitForAnswer()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