blob: 244694624840e966f4ad492050e5b4fb57ee79d6 [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
19import android.content.Context;
Jordan Liu8866f912019-10-18 12:06:35 -070020import android.os.Bundle;
Jordan Liudfcbfaf2019-10-11 11:42:03 -070021import android.telephony.CellBroadcastService;
22import android.telephony.SmsCbLocation;
23import android.telephony.SmsCbMessage;
24import android.telephony.SubscriptionManager;
25import android.telephony.TelephonyManager;
Jordan Liu8866f912019-10-18 12:06:35 -070026import android.telephony.cdma.CdmaSmsCbProgramData;
Jordan Liue532d232019-12-16 15:35:27 -080027import android.util.Log;
Jordan Liudfcbfaf2019-10-11 11:42:03 -070028
Jordan Liuc8e12392019-11-07 11:34:49 -080029import com.android.internal.annotations.VisibleForTesting;
30
Jordan Liu8866f912019-10-18 12:06:35 -070031import java.util.ArrayList;
32import java.util.List;
33import java.util.function.Consumer;
34
Jordan Liudfcbfaf2019-10-11 11:42:03 -070035/**
36 * The default implementation of CellBroadcastService, which is used for handling GSM and CDMA
37 * cell broadcast messages.
38 */
39public class DefaultCellBroadcastService extends CellBroadcastService {
40 private GsmCellBroadcastHandler mGsmCellBroadcastHandler;
41 private CellBroadcastHandler mCdmaCellBroadcastHandler;
Jordan Liu8866f912019-10-18 12:06:35 -070042 private CdmaServiceCategoryProgramHandler mCdmaScpHandler;
Jordan Liudfcbfaf2019-10-11 11:42:03 -070043
44 private static final String TAG = "DefaultCellBroadcastService";
45
46 private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7',
47 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
48
49 @Override
50 public void onCreate() {
51 super.onCreate();
52 mGsmCellBroadcastHandler =
53 GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(getApplicationContext());
54 mCdmaCellBroadcastHandler =
55 CellBroadcastHandler.makeCellBroadcastHandler(getApplicationContext());
Jordan Liu8866f912019-10-18 12:06:35 -070056 mCdmaScpHandler =
57 CdmaServiceCategoryProgramHandler.makeScpHandler(getApplicationContext());
Jordan Liudfcbfaf2019-10-11 11:42:03 -070058 }
59
60 @Override
Chen Xu74b654e2020-01-02 18:13:20 -080061 public void onDestroy() {
62 mGsmCellBroadcastHandler.cleanup();
63 mCdmaCellBroadcastHandler.cleanup();
64 super.onDestroy();
65 }
66
67 @Override
Jordan Liudfcbfaf2019-10-11 11:42:03 -070068 public void onGsmCellBroadcastSms(int slotIndex, byte[] message) {
Jordan Liue532d232019-12-16 15:35:27 -080069 Log.d(TAG, "onGsmCellBroadcastSms received message on slotId=" + slotIndex);
Jordan Liudfcbfaf2019-10-11 11:42:03 -070070 mGsmCellBroadcastHandler.onGsmCellBroadcastSms(slotIndex, message);
71 }
72
73 @Override
74 public void onCdmaCellBroadcastSms(int slotIndex, byte[] bearerData, int serviceCategory) {
Jordan Liue532d232019-12-16 15:35:27 -080075 Log.d(TAG, "onCdmaCellBroadcastSms received message on slotId=" + slotIndex);
Jordan Liudfcbfaf2019-10-11 11:42:03 -070076 int[] subIds =
77 ((SubscriptionManager) getSystemService(
78 Context.TELEPHONY_SUBSCRIPTION_SERVICE)).getSubscriptionIds(slotIndex);
79 String plmn;
80 if (subIds != null && subIds.length > 0) {
81 int subId = subIds[0];
82 plmn = ((TelephonyManager) getSystemService(
83 Context.TELEPHONY_SERVICE)).createForSubscriptionId(
84 subId).getNetworkOperator();
85 } else {
86 plmn = "";
87 }
Jordan Liuc8e12392019-11-07 11:34:49 -080088 SmsCbMessage message = parseBroadcastSms(getApplicationContext(), slotIndex, plmn,
89 bearerData, serviceCategory);
Jordan Liudfcbfaf2019-10-11 11:42:03 -070090 if (message != null) {
91 mCdmaCellBroadcastHandler.onCdmaCellBroadcastSms(message);
92 }
93 }
94
Jordan Liu8866f912019-10-18 12:06:35 -070095 @Override
96 public void onCdmaScpMessage(int slotIndex, List<CdmaSmsCbProgramData> programData,
97 String originatingAddress, Consumer<Bundle> callback) {
Jordan Liue532d232019-12-16 15:35:27 -080098 Log.d(TAG, "onCdmaScpMessage received message on slotId=" + slotIndex);
Jordan Liu8866f912019-10-18 12:06:35 -070099 mCdmaScpHandler.onCdmaScpMessage(slotIndex, new ArrayList<>(programData),
100 originatingAddress, callback);
101 }
102
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700103 /**
104 * Parses a CDMA broadcast SMS
105 *
106 * @param slotIndex the slotIndex the SMS was received on
107 * @param plmn the PLMN for a broadcast SMS or "" if unknown
108 * @param bearerData the bearerData of the SMS
109 * @param serviceCategory the service category of the broadcast
110 */
Jordan Liuc8e12392019-11-07 11:34:49 -0800111 @VisibleForTesting
112 public static SmsCbMessage parseBroadcastSms(Context context, int slotIndex, String plmn,
113 byte[] bearerData,
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700114 int serviceCategory) {
Jordan Liuc8e12392019-11-07 11:34:49 -0800115 BearerData bData = BearerData.decode(context, bearerData, serviceCategory);
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700116 if (bData == null) {
Jordan Liue532d232019-12-16 15:35:27 -0800117 Log.w(TAG, "BearerData.decode() returned null");
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700118 return null;
119 }
Jordan Liue532d232019-12-16 15:35:27 -0800120 Log.d(TAG, "MT raw BearerData = " + toHexString(bearerData, 0, bearerData.length));
Chen Xu7feb7b02019-12-05 23:52:05 -0800121 SmsCbLocation location = new SmsCbLocation(plmn, -1, -1);
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700122
Jack Yu515f34c2019-11-20 23:19:29 -0800123 SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
124 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
125 int subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
126 int[] subIds = sm.getSubscriptionIds(slotIndex);
127 if (subIds != null && subIds.length > 0) {
128 subId = subIds[0];
129 }
130
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700131 return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP2,
132 SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE, bData.messageId, location,
133 serviceCategory, bData.getLanguage(), bData.userData.payloadStr,
Jordan Liuac12bae2019-11-21 11:59:07 -0800134 bData.priority, null, bData.cmasWarningInfo, 0, null, System.currentTimeMillis(),
135 slotIndex, subId);
Jordan Liudfcbfaf2019-10-11 11:42:03 -0700136 }
137
138 private static String toHexString(byte[] array, int offset, int length) {
139 char[] buf = new char[length * 2];
140 int bufIndex = 0;
141 for (int i = offset; i < offset + length; i++) {
142 byte b = array[i];
143 buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
144 buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
145 }
146 return new String(buf);
147 }
148}