1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import static android.provider.Settings.Secure.CMAS_ADDITIONAL_BROADCAST_PKG; 20 21 import android.Manifest; 22 import android.app.Activity; 23 import android.app.AppOpsManager; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.os.Build; 27 import android.os.Message; 28 import android.os.UserHandle; 29 import android.provider.Settings; 30 import android.provider.Telephony; 31 import android.telephony.SmsCbMessage; 32 import android.telephony.SubscriptionManager; 33 34 import com.android.internal.telephony.metrics.TelephonyMetrics; 35 36 /** 37 * Dispatch new Cell Broadcasts to receivers. Acquires a private wakelock until the broadcast 38 * completes and our result receiver is called. 39 */ 40 public class CellBroadcastHandler extends WakeLockStateMachine { 41 CellBroadcastHandler(Context context, Phone phone)42 private CellBroadcastHandler(Context context, Phone phone) { 43 this("CellBroadcastHandler", context, phone); 44 } 45 CellBroadcastHandler(String debugTag, Context context, Phone phone)46 protected CellBroadcastHandler(String debugTag, Context context, Phone phone) { 47 super(debugTag, context, phone); 48 } 49 50 /** 51 * Create a new CellBroadcastHandler. 52 * @param context the context to use for dispatching Intents 53 * @return the new handler 54 */ makeCellBroadcastHandler(Context context, Phone phone)55 public static CellBroadcastHandler makeCellBroadcastHandler(Context context, Phone phone) { 56 CellBroadcastHandler handler = new CellBroadcastHandler(context, phone); 57 handler.start(); 58 return handler; 59 } 60 61 /** 62 * Handle Cell Broadcast messages from {@code CdmaInboundSmsHandler}. 63 * 3GPP-format Cell Broadcast messages sent from radio are handled in the subclass. 64 * 65 * @param message the message to process 66 * @return true if an ordered broadcast was sent; false on failure 67 */ 68 @Override handleSmsMessage(Message message)69 protected boolean handleSmsMessage(Message message) { 70 if (message.obj instanceof SmsCbMessage) { 71 handleBroadcastSms((SmsCbMessage) message.obj); 72 return true; 73 } else { 74 loge("handleMessage got object of type: " + message.obj.getClass().getName()); 75 return false; 76 } 77 } 78 79 /** 80 * Dispatch a Cell Broadcast message to listeners. 81 * @param message the Cell Broadcast to broadcast 82 */ handleBroadcastSms(SmsCbMessage message)83 protected void handleBroadcastSms(SmsCbMessage message) { 84 String receiverPermission; 85 int appOp; 86 87 // Log Cellbroadcast msg received event 88 TelephonyMetrics metrics = TelephonyMetrics.getInstance(); 89 metrics.writeNewCBSms(mPhone.getPhoneId(), message.getMessageFormat(), 90 message.getMessagePriority(), message.isCmasMessage(), message.isEtwsMessage(), 91 message.getServiceCategory()); 92 93 Intent intent; 94 if (message.isEmergencyMessage()) { 95 log("Dispatching emergency SMS CB, SmsCbMessage is: " + message); 96 intent = new Intent(Telephony.Sms.Intents.SMS_EMERGENCY_CB_RECEIVED_ACTION); 97 // Explicitly send the intent to the default cell broadcast receiver. 98 intent.setPackage(mContext.getResources().getString( 99 com.android.internal.R.string.config_defaultCellBroadcastReceiverPkg)); 100 receiverPermission = Manifest.permission.RECEIVE_EMERGENCY_BROADCAST; 101 appOp = AppOpsManager.OP_RECEIVE_EMERGECY_SMS; 102 } else { 103 log("Dispatching SMS CB, SmsCbMessage is: " + message); 104 intent = new Intent(Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION); 105 // Send implicit intent since there are various 3rd party carrier apps listen to 106 // this intent. 107 intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); 108 receiverPermission = Manifest.permission.RECEIVE_SMS; 109 appOp = AppOpsManager.OP_RECEIVE_SMS; 110 } 111 112 intent.putExtra("message", message); 113 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId()); 114 115 if (Build.IS_DEBUGGABLE) { 116 // Send additional broadcast intent to the specified package. This is only for sl4a 117 // automation tests. 118 final String additionalPackage = Settings.Secure.getString( 119 mContext.getContentResolver(), CMAS_ADDITIONAL_BROADCAST_PKG); 120 if (additionalPackage != null) { 121 Intent additionalIntent = new Intent(intent); 122 additionalIntent.setPackage(additionalPackage); 123 mContext.sendOrderedBroadcastAsUser(additionalIntent, UserHandle.ALL, 124 receiverPermission, appOp, null, getHandler(), Activity.RESULT_OK, null, 125 null); 126 } 127 } 128 129 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL, receiverPermission, appOp, 130 mReceiver, getHandler(), Activity.RESULT_OK, null, null); 131 } 132 } 133