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