1 /*
2  * Copyright (C) 2007-2008 Esmertec AG.
3  * Copyright (C) 2007-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.transaction;
19 
20 import android.app.Service;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.os.PowerManager;
25 import android.provider.Telephony.Sms.Intents;
26 
27 /**
28  * Handle incoming SMSes.  Just dispatches the work off to a Service.
29  */
30 public class SmsReceiver extends BroadcastReceiver {
31     static final Object mStartingServiceSync = new Object();
32     static PowerManager.WakeLock mStartingService;
33     private static SmsReceiver sInstance;
34 
getInstance()35     public static SmsReceiver getInstance() {
36         if (sInstance == null) {
37             sInstance = new SmsReceiver();
38         }
39         return sInstance;
40     }
41 
42     @Override
onReceive(Context context, Intent intent)43     public void onReceive(Context context, Intent intent) {
44         onReceiveWithPrivilege(context, intent, false);
45     }
46 
onReceiveWithPrivilege(Context context, Intent intent, boolean privileged)47     protected void onReceiveWithPrivilege(Context context, Intent intent, boolean privileged) {
48         // If 'privileged' is false, it means that the intent was delivered to the base
49         // no-permissions receiver class.  If we get an SMS_RECEIVED message that way, it
50         // means someone has tried to spoof the message by delivering it outside the normal
51         // permission-checked route, so we just ignore it.
52         if (!privileged && intent.getAction().equals(Intents.SMS_DELIVER_ACTION)) {
53             return;
54         }
55 
56         intent.setClass(context, SmsReceiverService.class);
57         intent.putExtra("result", getResultCode());
58         beginStartingService(context, intent);
59     }
60 
61     // N.B.: <code>beginStartingService</code> and
62     // <code>finishStartingService</code> were copied from
63     // <code>com.android.calendar.AlertReceiver</code>.  We should
64     // factor them out or, even better, improve the API for starting
65     // services under wake locks.
66 
67     /**
68      * Start the service to process the current event notifications, acquiring
69      * the wake lock before returning to ensure that the service will run.
70      */
beginStartingService(Context context, Intent intent)71     public static void beginStartingService(Context context, Intent intent) {
72         synchronized (mStartingServiceSync) {
73             if (mStartingService == null) {
74                 PowerManager pm =
75                     (PowerManager)context.getSystemService(Context.POWER_SERVICE);
76                 mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
77                         "StartingAlertService");
78                 mStartingService.setReferenceCounted(false);
79             }
80             mStartingService.acquire();
81             context.startService(intent);
82         }
83     }
84 
85     /**
86      * Called back by the service when it has finished processing notifications,
87      * releasing the wake lock if the service is now stopping.
88      */
finishStartingService(Service service, int startId)89     public static void finishStartingService(Service service, int startId) {
90         synchronized (mStartingServiceSync) {
91             if (mStartingService != null) {
92                 if (service.stopSelfResult(startId)) {
93                     mStartingService.release();
94                 }
95             }
96         }
97     }
98 }
99