blob: 1eddde13520d71d83132860a8523f9ad91a5061f [file] [log] [blame]
Jordan Liudfcbfaf2019-10-11 11:42:03 -07001/*
2 * Copyright (C) 2019 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
17package com.android.cellbroadcastservice;
18
Jordan Liu62e183f2019-12-20 15:09:44 -080019import static com.android.cellbroadcastservice.CellBroadcastStatsLog.CELL_BROADCAST_MESSAGE_ERROR__TYPE__CDMA_DECODING_ERROR;
20
Jack Yu90af67b2020-01-24 11:45:59 -080021import android.annotation.NonNull;
Jordan Liudfcbfaf2019-10-11 11:42:03 -070022import android.content.Context;
Jordan Liu8866f912019-10-18 12:06:35 -070023import android.os.Bundle;
Jordan Liudfcbfaf2019-10-11 11:42:03 -070024import android.telephony.CellBroadcastService;
25import android.telephony.SmsCbLocation;
26import android.telephony.SmsCbMessage;
27import android.telephony.SubscriptionManager;
28import android.telephony.TelephonyManager;
Jordan Liu8866f912019-10-18 12:06:35 -070029import android.telephony.cdma.CdmaSmsCbProgramData;
Jordan Liue532d232019-12-16 15:35:27 -080030import android.util.Log;
Jordan Liudfcbfaf2019-10-11 11:42:03 -070031
Jordan Liuc8e12392019-11-07 11:34:49 -080032import com.android.internal.annotations.VisibleForTesting;
33
Jordan Liu8866f912019-10-18 12:06:35 -070034import java.util.ArrayList;
35import java.util.List;
36import java.util.function.Consumer;
37
Jordan Liudfcbfaf2019-10-11 11:42:03 -070038/**
Jordan Liu62e183f2019-12-20 15:09:44 -080039 * The default implementation of CellBroadcastService, which is used for handling GSM and CDMA cell
40 * broadcast messages.
Jordan Liudfcbfaf2019-10-11 11:42:03 -070041 */
42public class DefaultCellBroadcastService extends CellBroadcastService {
43 private GsmCellBroadcastHandler mGsmCellBroadcastHandler;
44 private CellBroadcastHandler mCdmaCellBroadcastHandler;
Jordan Liu8866f912019-10-18 12:06:35 -070045 private CdmaServiceCategoryProgramHandler mCdmaScpHandler;
Jordan Liudfcbfaf2019-10-11 11:42:03 -070046
47 private static final String TAG = "DefaultCellBroadcastService";
48
Jordan Liu62e183f2019-12-20 15:09:44 -080049 private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7',
50 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
Jordan Liudfcbfaf2019-10-11 11:42:03 -070051
52 @Override
53 public void onCreate() {
54 super.onCreate();
55 mGsmCellBroadcastHandler =
56 GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(getApplicationContext());
57 mCdmaCellBroadcastHandler =
58 CellBroadcastHandler.makeCellBroadcastHandler(getApplicationContext());
Jordan Liu8866f912019-10-18 12:06:35 -070059 mCdmaScpHandler =
60 CdmaServiceCategoryProgramHandler.makeScpHandler(getApplicationContext());
Jordan Liudfcbfaf2019-10-11 11:42:03 -070061 }
62
63 @Override
Chen Xu74b654e2020-01-02 18:13:20 -080064 public void onDestroy() {
65 mGsmCellBroadcastHandler.cleanup();
66 mCdmaCellBroadcastHandler.cleanup();
67 super.onDestroy();
68 }
69
70 @Override
Jordan Liudfcbfaf2019-10-11 11:42:03 -070071 public void onGsmCellBroadcastSms(int slotIndex, byte[] message) {
Jordan Liue532d232019-12-16 15:35:27 -080072 Log.d(TAG, "onGsmCellBroadcastSms received message on slotId=" + slotIndex);
Jordan Liu62e183f2019-12-20 15:09:44 -080073 CellBroadcastStatsLog.write(CellBroadcastStatsLog.CB_MESSAGE_REPORTED,
74 CellBroadcastStatsLog.CELL_BROADCAST_MESSAGE_REPORTED__TYPE__GSM);
Jordan Liudfcbfaf2019-10-11 11:42:03 -070075 mGsmCellBroadcastHandler.onGsmCellBroadcastSms(slotIndex, message);
76 }
77
78 @Override
79 public void onCdmaCellBroadcastSms(int slotIndex, byte[] bearerData, int serviceCategory) {
Jordan Liue532d232019-12-16 15:35:27 -080080 Log.d(TAG, "onCdmaCellBroadcastSms received message on slotId=" + slotIndex);
Jordan Liu62e183f2019-12-20 15:09:44 -080081 CellBroadcastStatsLog.write(CellBroadcastStatsLog.CB_MESSAGE_REPORTED,
82 CellBroadcastStatsLog.CELL_BROADCAST_MESSAGE_REPORTED__TYPE__CDMA);
Jordan Liudfcbfaf2019-10-11 11:42:03 -070083 int[] subIds =
84 ((SubscriptionManager) getSystemService(
85 Context.TELEPHONY_SUBSCRIPTION_SERVICE)).getSubscriptionIds(slotIndex);
86 String plmn;
87 if (subIds != null && subIds.length > 0) {
88 int subId = subIds[0];
89 plmn = ((TelephonyManager) getSystemService(
Jordan Liu62e183f2019-12-20 15:09:44 -080090 Context.TELEPHONY_SERVICE)).createForSubscriptionId(
91 subId).getNetworkOperator();
Jordan Liudfcbfaf2019-10-11 11:42:03 -070092 } else {
93 plmn = "";
94 }
Jordan Liu62e183f2019-12-20 15:09:44 -080095 SmsCbMessage message = parseCdmaBroadcastSms(getApplicationContext(), slotIndex, plmn,
Jordan Liuc8e12392019-11-07 11:34:49 -080096 bearerData, serviceCategory);
Jordan Liudfcbfaf2019-10-11 11:42:03 -070097 if (message != null) {
98 mCdmaCellBroadcastHandler.onCdmaCellBroadcastSms(message);
99 }
100 }
101
Jordan Liu8866f912019-10-18 12:06:35 -0700102 @Override
103 public void onCdmaScpMessage(int slotIndex, List<CdmaSmsCbProgramData> programData,
104 String originatingAddress, Consumer<Bundle> callback) {
Jordan Liue532d232019-12-16 15:35:27 -0800105 Log.d(TAG, "onCdmaScpMessage received message on slotId=" + slotIndex);
Jordan Liu62e183f2019-12-20 15:09:44 -0800106 CellBroadcastStatsLog.write(CellBroadcastStatsLog.CB_MESSAGE_REPORTED,
107 CellBroadcastStatsLog.CELL_BROADCAST_MESSAGE_REPORTED__TYPE__CDMA_SPC);
Jordan Liu8866f912019-10-18 12:06:35 -0700108 mCdmaScpHandler.onCdmaScpMessage(slotIndex, new ArrayList<>(programData),
109 originatingAddress, callback);
110 }
111
Jack Yu90af67b2020-01-24 11:45:59 -0800112 @Override
113 public @NonNull String getCellBroadcastAreaInfo(int slotIndex) {
114 Log.d(TAG, "getCellBroadcastAreaInfo on slotId=" + slotIndex);
115 return mGsmCellBroadcastHandler.getCellBroadcastAreaInfo(slotIndex);
116 }
117
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700118 /**
119 * Parses a CDMA broadcast SMS
120 *
Jordan Liu62e183f2019-12-20 15:09:44 -0800121 * @param slotIndex the slotIndex the SMS was received on
122 * @param plmn the PLMN for a broadcast SMS or "" if unknown
123 * @param bearerData the bearerData of the SMS
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700124 * @param serviceCategory the service category of the broadcast
125 */
Jordan Liuc8e12392019-11-07 11:34:49 -0800126 @VisibleForTesting
Jordan Liu62e183f2019-12-20 15:09:44 -0800127 public static SmsCbMessage parseCdmaBroadcastSms(Context context, int slotIndex, String plmn,
Jordan Liuc8e12392019-11-07 11:34:49 -0800128 byte[] bearerData,
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700129 int serviceCategory) {
Jordan Liu62e183f2019-12-20 15:09:44 -0800130 BearerData bData;
131 try {
132 bData = BearerData.decode(context, bearerData, serviceCategory);
133 } catch (Exception e) {
134 Log.e(TAG, "Error decoding bearer data e=" + e.toString());
135 CellBroadcastStatsLog.write(CellBroadcastStatsLog.CB_MESSAGE_ERROR,
136 CELL_BROADCAST_MESSAGE_ERROR__TYPE__CDMA_DECODING_ERROR, e.toString());
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700137 return null;
138 }
Jordan Liue532d232019-12-16 15:35:27 -0800139 Log.d(TAG, "MT raw BearerData = " + toHexString(bearerData, 0, bearerData.length));
Chen Xu7feb7b02019-12-05 23:52:05 -0800140 SmsCbLocation location = new SmsCbLocation(plmn, -1, -1);
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700141
Jack Yu515f34c2019-11-20 23:19:29 -0800142 SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
143 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
144 int subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
145 int[] subIds = sm.getSubscriptionIds(slotIndex);
146 if (subIds != null && subIds.length > 0) {
147 subId = subIds[0];
148 }
149
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700150 return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP2,
151 SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE, bData.messageId, location,
Jack Yu28325462020-02-03 16:29:26 -0800152 serviceCategory, bData.getLanguage(), bData.userData.msgEncoding,
153 bData.userData.payloadStr, bData.priority, null, bData.cmasWarningInfo, 0, null,
154 System.currentTimeMillis(), slotIndex, subId);
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700155 }
156
157 private static String toHexString(byte[] array, int offset, int length) {
158 char[] buf = new char[length * 2];
159 int bufIndex = 0;
160 for (int i = offset; i < offset + length; i++) {
161 byte b = array[i];
162 buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
163 buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
164 }
165 return new String(buf);
166 }
167}