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