Skip to content

Commit 3e3c3f8

Browse files
author
Jake Hamby
committed
Add support for CMAS warning notifications over CDMA.
Refactor SMS Cell Broadcast support to enable receiving CMAS warning notifications over CDMA. The CellBroadcastReceiver app must also be updated with the corresponding change. All cell broadcasts are now delivered as a Parcelable SmsCbMessage object in the "message" extra of the SMS_CB_RECEIVED_ACTION or SMS_EMERGENCY_CB_RECEIVED_ACTION, instead of as a GSM/UMTS "pdu" byte array. Existing functionality for ETWS and CMAS alerts over GSM/UMTS continues to be supported using the new radio-technology independent SmsCbMessage and related objects. Test cases are added to verify that valid and invalid broadcast data is handled appropriately. Unit testing discovered a bug in the BitwiseOutputStream utility class used by the added test cases. When the BitwiseOutputStream object must be expanded (in the private possExpand() method), the mEnd field is not updated to the new array size. This causes a new array to be allocated on every new write, and for all data beyond the original array allocation to be replaced with zeroes. Fixed by adding a line to possExpand() to update mEnd. Added a test case to BitwiseStreamsTest to verify the fix. Besides the test cases, BitwiseOutputStream is only used by BearerData in two places, both of which allocate a sufficient initial buffer. So the bug in BitwiseOutputStream is not critical to fix for normal operation, but should be fixed so that the test cases using it function correctly. Bug: 5856308 Change-Id: I201ecbf11607fd200aaae3cbb32561efabf65672
1 parent 9dc348d commit 3e3c3f8

File tree

20 files changed

+3063
-579
lines changed

20 files changed

+3063
-579
lines changed

core/java/android/provider/Telephony.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -596,8 +596,8 @@ public static final class Intents {
596596
* values:</p>
597597
*
598598
* <ul>
599-
* <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs
600-
* that make up the message.</li>
599+
* <li><em>message</em> - An SmsCbMessage object containing the broadcast message
600+
* data. This is not an emergency alert, so ETWS and CMAS data will be null.</li>
601601
* </ul>
602602
*
603603
* <p>The extra values can be extracted using
@@ -616,8 +616,8 @@ public static final class Intents {
616616
* values:</p>
617617
*
618618
* <ul>
619-
* <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs
620-
* that make up the message.</li>
619+
* <li><em>message</em> - An SmsCbMessage object containing the broadcast message
620+
* data, including ETWS or CMAS warning notification info if present.</li>
621621
* </ul>
622622
*
623623
* <p>The extra values can be extracted using
@@ -630,6 +630,26 @@ public static final class Intents {
630630
public static final String SMS_EMERGENCY_CB_RECEIVED_ACTION =
631631
"android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED";
632632

633+
/**
634+
* Broadcast Action: A new CDMA SMS has been received containing Service Category
635+
* Program Data (updates the list of enabled broadcast channels). The intent will
636+
* have the following extra values:</p>
637+
*
638+
* <ul>
639+
* <li><em>operations</em> - An array of CdmaSmsCbProgramData objects containing
640+
* the service category operations (add/delete/clear) to perform.</li>
641+
* </ul>
642+
*
643+
* <p>The extra values can be extracted using
644+
* {@link #getMessagesFromIntent(Intent)}.</p>
645+
*
646+
* <p>If a BroadcastReceiver encounters an error while processing
647+
* this intent it should set the result code appropriately.</p>
648+
*/
649+
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
650+
public static final String SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION =
651+
"android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED";
652+
633653
/**
634654
* Broadcast Action: The SIM storage for SMS messages is full. If
635655
* space is not freed, messages targeted for the SIM (class 2) may

core/java/com/android/internal/util/BitwiseOutputStream.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ private void possExpand(int bits) {
7777
byte[] newBuf = new byte[(mPos + bits) >>> 2];
7878
System.arraycopy(mBuf, 0, newBuf, 0, mEnd >>> 3);
7979
mBuf = newBuf;
80+
mEnd = newBuf.length << 3;
8081
}
8182

8283
/**

core/tests/coretests/src/com/android/internal/util/BitwiseStreamsTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,25 @@ public void testSix() throws Exception {
133133
long end = android.os.SystemClock.elapsedRealtime();
134134
Log.d(LOG_TAG, "repeated encode-decode took " + (end - start) + " ms");
135135
}
136+
137+
@SmallTest
138+
public void testExpandArray() throws Exception {
139+
Random random = new Random();
140+
int iterations = 10000;
141+
int[] sizeArr = new int[iterations];
142+
int[] valueArr = new int[iterations];
143+
BitwiseOutputStream outStream = new BitwiseOutputStream(8);
144+
for (int i = 0; i < iterations; i++) {
145+
int x = random.nextInt();
146+
int size = (x & 0x07) + 1;
147+
int value = x & (-1 >>> (32 - size));
148+
sizeArr[i] = size;
149+
valueArr[i] = value;
150+
outStream.write(size, value);
151+
}
152+
BitwiseInputStream inStream = new BitwiseInputStream(outStream.toByteArray());
153+
for (int i = 0; i < iterations; i++) {
154+
assertEquals(valueArr[i], inStream.read(sizeArr[i]));
155+
}
156+
}
136157
}
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
/*
2+
* Copyright (C) 2012 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 android.telephony;
18+
19+
import android.os.Parcel;
20+
import android.os.Parcelable;
21+
22+
/**
23+
* Contains CMAS warning notification Type 1 elements for a {@link SmsCbMessage}.
24+
* Supported values for each element are defined in TIA-1149-0-1 (CMAS over CDMA) and
25+
* 3GPP TS 23.041 (for GSM/UMTS).
26+
*
27+
* {@hide}
28+
*/
29+
public class SmsCbCmasInfo implements Parcelable {
30+
31+
// CMAS message class (in GSM/UMTS message identifier or CDMA service category).
32+
33+
/** Presidential-level alert (Korean Public Alert System Class 0 message). */
34+
public static final int CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT = 0x00;
35+
36+
/** Extreme threat to life and property (Korean Public Alert System Class 1 message). */
37+
public static final int CMAS_CLASS_EXTREME_THREAT = 0x01;
38+
39+
/** Severe threat to life and property (Korean Public Alert System Class 1 message). */
40+
public static final int CMAS_CLASS_SEVERE_THREAT = 0x02;
41+
42+
/** Child abduction emergency (AMBER Alert). */
43+
public static final int CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY = 0x03;
44+
45+
/** CMAS test message. */
46+
public static final int CMAS_CLASS_REQUIRED_MONTHLY_TEST = 0x04;
47+
48+
/** CMAS exercise. */
49+
public static final int CMAS_CLASS_CMAS_EXERCISE = 0x05;
50+
51+
/** CMAS category for operator defined use. */
52+
public static final int CMAS_CLASS_OPERATOR_DEFINED_USE = 0x06;
53+
54+
/** CMAS category for warning types that are reserved for future extension. */
55+
public static final int CMAS_CLASS_UNKNOWN = -1;
56+
57+
// CMAS alert category (in CDMA type 1 elements record).
58+
59+
/** CMAS alert category: Geophysical including landslide. */
60+
public static final int CMAS_CATEGORY_GEO = 0x00;
61+
62+
/** CMAS alert category: Meteorological including flood. */
63+
public static final int CMAS_CATEGORY_MET = 0x01;
64+
65+
/** CMAS alert category: General emergency and public safety. */
66+
public static final int CMAS_CATEGORY_SAFETY = 0x02;
67+
68+
/** CMAS alert category: Law enforcement, military, homeland/local/private security. */
69+
public static final int CMAS_CATEGORY_SECURITY = 0x03;
70+
71+
/** CMAS alert category: Rescue and recovery. */
72+
public static final int CMAS_CATEGORY_RESCUE = 0x04;
73+
74+
/** CMAS alert category: Fire suppression and rescue. */
75+
public static final int CMAS_CATEGORY_FIRE = 0x05;
76+
77+
/** CMAS alert category: Medical and public health. */
78+
public static final int CMAS_CATEGORY_HEALTH = 0x06;
79+
80+
/** CMAS alert category: Pollution and other environmental. */
81+
public static final int CMAS_CATEGORY_ENV = 0x07;
82+
83+
/** CMAS alert category: Public and private transportation. */
84+
public static final int CMAS_CATEGORY_TRANSPORT = 0x08;
85+
86+
/** CMAS alert category: Utility, telecom, other non-transport infrastructure. */
87+
public static final int CMAS_CATEGORY_INFRA = 0x09;
88+
89+
/** CMAS alert category: Chem, bio, radiological, nuclear, high explosive threat or attack. */
90+
public static final int CMAS_CATEGORY_CBRNE = 0x0a;
91+
92+
/** CMAS alert category: Other events. */
93+
public static final int CMAS_CATEGORY_OTHER = 0x0b;
94+
95+
/**
96+
* CMAS alert category is unknown. The category is only available for CDMA broadcasts
97+
* containing a type 1 elements record, so GSM and UMTS broadcasts always return unknown.
98+
*/
99+
public static final int CMAS_CATEGORY_UNKNOWN = -1;
100+
101+
// CMAS response type (in CDMA type 1 elements record).
102+
103+
/** CMAS response type: Take shelter in place. */
104+
public static final int CMAS_RESPONSE_TYPE_SHELTER = 0x00;
105+
106+
/** CMAS response type: Evacuate (Relocate). */
107+
public static final int CMAS_RESPONSE_TYPE_EVACUATE = 0x01;
108+
109+
/** CMAS response type: Make preparations. */
110+
public static final int CMAS_RESPONSE_TYPE_PREPARE = 0x02;
111+
112+
/** CMAS response type: Execute a pre-planned activity. */
113+
public static final int CMAS_RESPONSE_TYPE_EXECUTE = 0x03;
114+
115+
/** CMAS response type: Attend to information sources. */
116+
public static final int CMAS_RESPONSE_TYPE_MONITOR = 0x04;
117+
118+
/** CMAS response type: Avoid hazard. */
119+
public static final int CMAS_RESPONSE_TYPE_AVOID = 0x05;
120+
121+
/** CMAS response type: Evaluate the information in this message (not for public warnings). */
122+
public static final int CMAS_RESPONSE_TYPE_ASSESS = 0x06;
123+
124+
/** CMAS response type: No action recommended. */
125+
public static final int CMAS_RESPONSE_TYPE_NONE = 0x07;
126+
127+
/**
128+
* CMAS response type is unknown. The response type is only available for CDMA broadcasts
129+
* containing a type 1 elements record, so GSM and UMTS broadcasts always return unknown.
130+
*/
131+
public static final int CMAS_RESPONSE_TYPE_UNKNOWN = -1;
132+
133+
// 4-bit CMAS severity (in GSM/UMTS message identifier or CDMA type 1 elements record).
134+
135+
/** CMAS severity type: Extraordinary threat to life or property. */
136+
public static final int CMAS_SEVERITY_EXTREME = 0x0;
137+
138+
/** CMAS severity type: Significant threat to life or property. */
139+
public static final int CMAS_SEVERITY_SEVERE = 0x1;
140+
141+
/**
142+
* CMAS alert severity is unknown. The severity is available for CDMA warning alerts
143+
* containing a type 1 elements record and for all GSM and UMTS alerts except for the
144+
* Presidential-level alert class (Korean Public Alert System Class 0).
145+
*/
146+
public static final int CMAS_SEVERITY_UNKNOWN = -1;
147+
148+
// CMAS urgency (in GSM/UMTS message identifier or CDMA type 1 elements record).
149+
150+
/** CMAS urgency type: Responsive action should be taken immediately. */
151+
public static final int CMAS_URGENCY_IMMEDIATE = 0x0;
152+
153+
/** CMAS urgency type: Responsive action should be taken within the next hour. */
154+
public static final int CMAS_URGENCY_EXPECTED = 0x1;
155+
156+
/**
157+
* CMAS alert urgency is unknown. The urgency is available for CDMA warning alerts
158+
* containing a type 1 elements record and for all GSM and UMTS alerts except for the
159+
* Presidential-level alert class (Korean Public Alert System Class 0).
160+
*/
161+
public static final int CMAS_URGENCY_UNKNOWN = -1;
162+
163+
// CMAS certainty (in GSM/UMTS message identifier or CDMA type 1 elements record).
164+
165+
/** CMAS certainty type: Determined to have occurred or to be ongoing. */
166+
public static final int CMAS_CERTAINTY_OBSERVED = 0x0;
167+
168+
/** CMAS certainty type: Likely (probability > ~50%). */
169+
public static final int CMAS_CERTAINTY_LIKELY = 0x1;
170+
171+
/**
172+
* CMAS alert certainty is unknown. The certainty is available for CDMA warning alerts
173+
* containing a type 1 elements record and for all GSM and UMTS alerts except for the
174+
* Presidential-level alert class (Korean Public Alert System Class 0).
175+
*/
176+
public static final int CMAS_CERTAINTY_UNKNOWN = -1;
177+
178+
/** CMAS message class. */
179+
private final int mMessageClass;
180+
181+
/** CMAS category. */
182+
private final int mCategory;
183+
184+
/** CMAS response type. */
185+
private final int mResponseType;
186+
187+
/** CMAS severity. */
188+
private final int mSeverity;
189+
190+
/** CMAS urgency. */
191+
private final int mUrgency;
192+
193+
/** CMAS certainty. */
194+
private final int mCertainty;
195+
196+
/** Create a new SmsCbCmasInfo object with the specified values. */
197+
public SmsCbCmasInfo(int messageClass, int category, int responseType, int severity,
198+
int urgency, int certainty) {
199+
mMessageClass = messageClass;
200+
mCategory = category;
201+
mResponseType = responseType;
202+
mSeverity = severity;
203+
mUrgency = urgency;
204+
mCertainty = certainty;
205+
}
206+
207+
/** Create a new SmsCbCmasInfo object from a Parcel. */
208+
SmsCbCmasInfo(Parcel in) {
209+
mMessageClass = in.readInt();
210+
mCategory = in.readInt();
211+
mResponseType = in.readInt();
212+
mSeverity = in.readInt();
213+
mUrgency = in.readInt();
214+
mCertainty = in.readInt();
215+
}
216+
217+
/**
218+
* Flatten this object into a Parcel.
219+
*
220+
* @param dest The Parcel in which the object should be written.
221+
* @param flags Additional flags about how the object should be written (ignored).
222+
*/
223+
@Override
224+
public void writeToParcel(Parcel dest, int flags) {
225+
dest.writeInt(mMessageClass);
226+
dest.writeInt(mCategory);
227+
dest.writeInt(mResponseType);
228+
dest.writeInt(mSeverity);
229+
dest.writeInt(mUrgency);
230+
dest.writeInt(mCertainty);
231+
}
232+
233+
/**
234+
* Returns the CMAS message class, e.g. {@link #CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT}.
235+
* @return one of the {@code CMAS_CLASS} values
236+
*/
237+
public int getMessageClass() {
238+
return mMessageClass;
239+
}
240+
241+
/**
242+
* Returns the CMAS category, e.g. {@link #CMAS_CATEGORY_GEO}.
243+
* @return one of the {@code CMAS_CATEGORY} values
244+
*/
245+
public int getCategory() {
246+
return mCategory;
247+
}
248+
249+
/**
250+
* Returns the CMAS response type, e.g. {@link #CMAS_RESPONSE_TYPE_SHELTER}.
251+
* @return one of the {@code CMAS_RESPONSE_TYPE} values
252+
*/
253+
public int getResponseType() {
254+
return mResponseType;
255+
}
256+
257+
/**
258+
* Returns the CMAS severity, e.g. {@link #CMAS_SEVERITY_EXTREME}.
259+
* @return one of the {@code CMAS_SEVERITY} values
260+
*/
261+
public int getSeverity() {
262+
return mSeverity;
263+
}
264+
265+
/**
266+
* Returns the CMAS urgency, e.g. {@link #CMAS_URGENCY_IMMEDIATE}.
267+
* @return one of the {@code CMAS_URGENCY} values
268+
*/
269+
public int getUrgency() {
270+
return mUrgency;
271+
}
272+
273+
/**
274+
* Returns the CMAS certainty, e.g. {@link #CMAS_CERTAINTY_OBSERVED}.
275+
* @return one of the {@code CMAS_CERTAINTY} values
276+
*/
277+
public int getCertainty() {
278+
return mCertainty;
279+
}
280+
281+
@Override
282+
public String toString() {
283+
return "SmsCbCmasInfo{messageClass=" + mMessageClass + ", category=" + mCategory
284+
+ ", responseType=" + mResponseType + ", severity=" + mSeverity
285+
+ ", urgency=" + mUrgency + ", certainty=" + mCertainty + '}';
286+
}
287+
288+
/**
289+
* Describe the kinds of special objects contained in the marshalled representation.
290+
* @return a bitmask indicating this Parcelable contains no special objects
291+
*/
292+
@Override
293+
public int describeContents() {
294+
return 0;
295+
}
296+
297+
/** Creator for unparcelling objects. */
298+
public static final Parcelable.Creator<SmsCbCmasInfo>
299+
CREATOR = new Parcelable.Creator<SmsCbCmasInfo>() {
300+
public SmsCbCmasInfo createFromParcel(Parcel in) {
301+
return new SmsCbCmasInfo(in);
302+
}
303+
304+
public SmsCbCmasInfo[] newArray(int size) {
305+
return new SmsCbCmasInfo[size];
306+
}
307+
};
308+
}

0 commit comments

Comments
 (0)