1 /*
2  * Copyright (C) 2011 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.cellbroadcastreceiver;
18 
19 import android.content.Context;
20 import android.database.Cursor;
21 import android.provider.Telephony;
22 import android.telephony.SmsCbCmasInfo;
23 import android.telephony.SmsCbEtwsInfo;
24 import android.telephony.SmsCbLocation;
25 import android.telephony.SmsCbMessage;
26 import android.telephony.SubscriptionManager;
27 import android.util.ArrayMap;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import android.widget.CheckedTextView;
32 import android.widget.CursorAdapter;
33 
34 /**
35  * The back-end data adapter for {@link CellBroadcastListActivity}.
36  */
37 public class CellBroadcastCursorAdapter extends CursorAdapter {
38 
39     private static boolean sIsActionMode = false;
40     private CheckedTextView mCheckedTextView;
41     private ArrayMap<Integer, Long> mSelectedMessages;
42 
CellBroadcastCursorAdapter(Context context, ArrayMap<Integer, Long> selectedMessages)43     public CellBroadcastCursorAdapter(Context context, ArrayMap<Integer, Long> selectedMessages) {
44         // don't set FLAG_AUTO_REQUERY or FLAG_REGISTER_CONTENT_OBSERVER
45         super(context, null, 0);
46         mSelectedMessages = selectedMessages;
47     }
48 
49     /**
50      * Makes a new view to hold the data pointed to by cursor.
51      * @param context Interface to application's global information
52      * @param cursor The cursor from which to get the data. The cursor is already
53      * moved to the correct position.
54      * @param parent The parent to which the new view is attached to
55      * @return the newly created view.
56      */
57     @Override
newView(Context context, Cursor cursor, ViewGroup parent)58     public View newView(Context context, Cursor cursor, ViewGroup parent) {
59         SmsCbMessage message = createFromCursor(context, cursor);
60 
61         LayoutInflater factory = LayoutInflater.from(context);
62         CellBroadcastListItem listItem = (CellBroadcastListItem) factory.inflate(
63                     R.layout.cell_broadcast_list_item, parent, false);
64 
65         listItem.bind(message);
66         return listItem;
67     }
68 
createFromCursor(Context context, Cursor cursor)69     static SmsCbMessage createFromCursor(Context context, Cursor cursor) {
70         int geoScope = cursor.getInt(
71                 cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.GEOGRAPHICAL_SCOPE));
72         int serialNum = cursor.getInt(
73                 cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.SERIAL_NUMBER));
74         int category = cursor.getInt(
75                 cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.SERVICE_CATEGORY));
76         String language = cursor.getString(
77                 cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.LANGUAGE_CODE));
78         String body = cursor.getString(
79                 cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.MESSAGE_BODY));
80         int format = cursor.getInt(
81                 cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.MESSAGE_FORMAT));
82         int priority = cursor.getInt(
83                 cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.MESSAGE_PRIORITY));
84         int slotIndex = cursor.getInt(
85                 cursor.getColumnIndexOrThrow(Telephony.CellBroadcasts.SLOT_INDEX));
86 
87         String plmn;
88         int plmnColumn = cursor.getColumnIndex(Telephony.CellBroadcasts.PLMN);
89         if (plmnColumn != -1 && !cursor.isNull(plmnColumn)) {
90             plmn = cursor.getString(plmnColumn);
91         } else {
92             plmn = null;
93         }
94 
95         int lac;
96         int lacColumn = cursor.getColumnIndex(Telephony.CellBroadcasts.LAC);
97         if (lacColumn != -1 && !cursor.isNull(lacColumn)) {
98             lac = cursor.getInt(lacColumn);
99         } else {
100             lac = -1;
101         }
102 
103         int cid;
104         int cidColumn = cursor.getColumnIndex(Telephony.CellBroadcasts.CID);
105         if (cidColumn != -1 && !cursor.isNull(cidColumn)) {
106             cid = cursor.getInt(cidColumn);
107         } else {
108             cid = -1;
109         }
110 
111         SmsCbLocation location = new SmsCbLocation(plmn, lac, cid);
112 
113         SmsCbEtwsInfo etwsInfo;
114         int etwsWarningTypeColumn = cursor.getColumnIndex(
115                 Telephony.CellBroadcasts.ETWS_WARNING_TYPE);
116         if (etwsWarningTypeColumn != -1 && !cursor.isNull(etwsWarningTypeColumn)) {
117             int warningType = cursor.getInt(etwsWarningTypeColumn);
118             etwsInfo = new SmsCbEtwsInfo(warningType, false, false, false, null);
119         } else {
120             etwsInfo = null;
121         }
122 
123         SmsCbCmasInfo cmasInfo;
124         int cmasMessageClassColumn = cursor.getColumnIndex(
125                 Telephony.CellBroadcasts.CMAS_MESSAGE_CLASS);
126         if (cmasMessageClassColumn != -1 && !cursor.isNull(cmasMessageClassColumn)) {
127             int messageClass = cursor.getInt(cmasMessageClassColumn);
128 
129             int cmasCategory;
130             int cmasCategoryColumn = cursor.getColumnIndex(
131                     Telephony.CellBroadcasts.CMAS_CATEGORY);
132             if (cmasCategoryColumn != -1 && !cursor.isNull(cmasCategoryColumn)) {
133                 cmasCategory = cursor.getInt(cmasCategoryColumn);
134             } else {
135                 cmasCategory = SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN;
136             }
137 
138             int responseType;
139             int cmasResponseTypeColumn = cursor.getColumnIndex(
140                     Telephony.CellBroadcasts.CMAS_RESPONSE_TYPE);
141             if (cmasResponseTypeColumn != -1 && !cursor.isNull(cmasResponseTypeColumn)) {
142                 responseType = cursor.getInt(cmasResponseTypeColumn);
143             } else {
144                 responseType = SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN;
145             }
146 
147             int severity;
148             int cmasSeverityColumn = cursor.getColumnIndex(
149                     Telephony.CellBroadcasts.CMAS_SEVERITY);
150             if (cmasSeverityColumn != -1 && !cursor.isNull(cmasSeverityColumn)) {
151                 severity = cursor.getInt(cmasSeverityColumn);
152             } else {
153                 severity = SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN;
154             }
155 
156             int urgency;
157             int cmasUrgencyColumn = cursor.getColumnIndex(
158                     Telephony.CellBroadcasts.CMAS_URGENCY);
159             if (cmasUrgencyColumn != -1 && !cursor.isNull(cmasUrgencyColumn)) {
160                 urgency = cursor.getInt(cmasUrgencyColumn);
161             } else {
162                 urgency = SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN;
163             }
164 
165             int certainty;
166             int cmasCertaintyColumn = cursor.getColumnIndex(
167                     Telephony.CellBroadcasts.CMAS_CERTAINTY);
168             if (cmasCertaintyColumn != -1 && !cursor.isNull(cmasCertaintyColumn)) {
169                 certainty = cursor.getInt(cmasCertaintyColumn);
170             } else {
171                 certainty = SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN;
172             }
173 
174             cmasInfo = new SmsCbCmasInfo(messageClass, cmasCategory, responseType, severity,
175                     urgency, certainty);
176         } else {
177             cmasInfo = null;
178         }
179 
180         String timeColumn = null;
181         if (cursor.getColumnIndex(Telephony.CellBroadcasts.DELIVERY_TIME) >= 0) {
182             timeColumn = Telephony.CellBroadcasts.DELIVERY_TIME;
183         } else if (cursor.getColumnIndex(Telephony.CellBroadcasts.RECEIVED_TIME) >= 0) {
184             timeColumn = Telephony.CellBroadcasts.RECEIVED_TIME;
185         }
186 
187         long time = cursor.getLong(cursor.getColumnIndexOrThrow(timeColumn));
188 
189         int dcs = 0;
190         if (cursor.getColumnIndex(Telephony.CellBroadcasts.DATA_CODING_SCHEME) >= 0) {
191             dcs = cursor.getInt(cursor.getColumnIndexOrThrow(
192                     Telephony.CellBroadcasts.DATA_CODING_SCHEME));
193         }
194 
195         SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
196                 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
197         int subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
198         int[] subIds = sm.getSubscriptionIds(slotIndex);
199         if (subIds != null && subIds.length > 0) {
200             subId = subIds[0];
201         }
202 
203         int maximumWaitTimeSec = 0;
204         if (cursor.getColumnIndex(Telephony.CellBroadcasts.MAXIMUM_WAIT_TIME) >= 0) {
205             maximumWaitTimeSec = cursor.getInt(cursor.getColumnIndexOrThrow(
206                     Telephony.CellBroadcasts.MAXIMUM_WAIT_TIME));
207         }
208 
209         return new SmsCbMessage(format, geoScope, serialNum, location, category, language, dcs,
210                 body, priority, etwsInfo, cmasInfo, maximumWaitTimeSec, null, time,
211                 slotIndex, subId);
212     }
213 
214     /**
215      * Bind an existing view to the data pointed to by cursor
216      * @param view Existing view, returned earlier by newView
217      * @param context Interface to application's global information
218      * @param cursor The cursor from which to get the data. The cursor is already
219      * moved to the correct position.
220      */
221     @Override
bindView(View view, Context context, Cursor cursor)222     public void bindView(View view, Context context, Cursor cursor) {
223         SmsCbMessage message = createFromCursor(context, cursor);
224         CellBroadcastListItem listItem = (CellBroadcastListItem) view;
225         mCheckedTextView = view.findViewById(R.id.checkBox);
226         updateCheckTextViewVisibility();
227         checkIsSelected(cursor.getPosition());
228         listItem.bind(message);
229     }
230 
setIsActionMode(boolean value)231     static void setIsActionMode(boolean value) {
232         sIsActionMode = value;
233     }
234 
updateCheckTextViewVisibility()235     void updateCheckTextViewVisibility() {
236         if (sIsActionMode) {
237             mCheckedTextView.setVisibility(View.VISIBLE);
238         } else {
239             mCheckedTextView.setVisibility(View.GONE);
240         }
241     }
242 
checkIsSelected(int position)243     void checkIsSelected(int position) {
244         if (mSelectedMessages.containsKey(position)) {
245             mCheckedTextView.setChecked(true);
246         } else {
247             mCheckedTextView.setChecked(false);
248         }
249     }
250 }
251