• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE;
20 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_ACTION;
21 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_CLASS;
22 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE;
23 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEY;
24 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEYWORDS;
25 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SCREEN_TITLE;
26 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_TITLE;
27 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME;
28 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID;
29 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION;
30 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS;
31 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE;
32 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RANK;
33 import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID;
34 import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
35 import static android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS;
36 import static android.provider.SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS;
37 
38 import android.annotation.Nullable;
39 import android.content.Context;
40 import android.content.Intent;
41 import android.content.pm.PackageManager;
42 import android.content.res.Resources;
43 import android.database.Cursor;
44 import android.database.MatrixCursor;
45 import android.provider.SearchIndexableResource;
46 import android.provider.SearchIndexablesProvider;
47 import android.telephony.SubscriptionManager;
48 import android.text.TextUtils;
49 
50 import com.android.internal.annotations.VisibleForTesting;
51 
52 import java.util.ArrayList;
53 import java.util.List;
54 
55 public class CellBroadcastSearchIndexableProvider extends SearchIndexablesProvider {
56 
57     @VisibleForTesting
58     // Additional keywords for settings search
59     public static final int[] INDEXABLE_KEYWORDS_RESOURCES = {
60             R.string.etws_earthquake_warning,
61             R.string.etws_tsunami_warning,
62             R.string.cmas_presidential_level_alert,
63             R.string.cmas_required_monthly_test,
64             R.string.emergency_alerts_title
65     };
66 
67     @VisibleForTesting
68     public static final SearchIndexableResource[] INDEXABLE_RES = new SearchIndexableResource[] {
69             new SearchIndexableResource(1, R.xml.preferences,
70                     CellBroadcastSettings.class.getName(),
71                     R.mipmap.ic_launcher_cell_broadcast),
72     };
73 
74     /**
75      * this method is to make this class unit-testable, because super.getContext() is a final
76      * method and therefore not mockable
77      * @return context
78      */
79     @VisibleForTesting
getContextMethod()80     public @Nullable Context getContextMethod() {
81         return super.getContext();
82     }
83 
84     /**
85      * this method is to make this class unit-testable, because
86      * CellBroadcastSettings.getResourcesForDefaultSubId() is a static method and cannot be stubbed.
87      * @return resources
88      */
89     @VisibleForTesting
getResourcesMethod()90     public Resources getResourcesMethod() {
91         return CellBroadcastSettings.getResourcesForDefaultSubId(getContextMethod());
92     }
93 
94     /**
95      * this method is to make this class unit-testable, because
96      * CellBroadcastSettings.isTestAlertsToggleVisible is a static method and therefore not mockable
97      * @return true if test alerts toggle is Visible
98      */
99     @VisibleForTesting
isTestAlertsToggleVisible()100     public boolean isTestAlertsToggleVisible() {
101         return CellBroadcastSettings.isTestAlertsToggleVisible(getContextMethod());
102     }
103 
104     @Override
onCreate()105     public boolean onCreate() {
106         return true;
107     }
108 
109     @Override
queryXmlResources(String[] projection)110     public Cursor queryXmlResources(String[] projection) {
111         if (isAutomotive()) {
112             return null;
113         }
114 
115         if (isDisableAllCbMessages()) {
116             return null;
117         }
118 
119         MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS);
120         final int count = INDEXABLE_RES.length;
121         for (int n = 0; n < count; n++) {
122             Object[] ref = new Object[7];
123             ref[COLUMN_INDEX_XML_RES_RANK] = INDEXABLE_RES[n].rank;
124             ref[COLUMN_INDEX_XML_RES_RESID] = INDEXABLE_RES[n].xmlResId;
125             ref[COLUMN_INDEX_XML_RES_CLASS_NAME] = null;
126             ref[COLUMN_INDEX_XML_RES_ICON_RESID] = INDEXABLE_RES[n].iconResId;
127             ref[COLUMN_INDEX_XML_RES_INTENT_ACTION] = Intent.ACTION_MAIN;
128             ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE] = getContextMethod().getPackageName();
129             ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS] = INDEXABLE_RES[n].className;
130             cursor.addRow(ref);
131         }
132         return cursor;
133     }
134 
135     @Override
queryRawData(String[] projection)136     public Cursor queryRawData(String[] projection) {
137         if (isAutomotive()) {
138             return null;
139         }
140 
141         if (isDisableAllCbMessages()) {
142             return null;
143         }
144 
145         MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
146         final Resources res = getResourcesMethod();
147 
148         Object[] raw = new Object[INDEXABLES_RAW_COLUMNS.length];
149         raw[COLUMN_INDEX_RAW_TITLE] = res.getString(R.string.sms_cb_settings);
150         List<String> keywordList = new ArrayList<>();
151         for (int keywordRes : INDEXABLE_KEYWORDS_RESOURCES) {
152             keywordList.add(res.getString(keywordRes));
153         }
154 
155         CellBroadcastChannelManager channelManager = new CellBroadcastChannelManager(
156                 getContextMethod(),
157                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
158 
159         if (!channelManager.getCellBroadcastChannelRanges(
160                 R.array.public_safety_messages_channels_range_strings).isEmpty()) {
161             keywordList.add(res.getString(R.string.public_safety_message));
162         }
163 
164         if (!channelManager.getCellBroadcastChannelRanges(
165                 R.array.state_local_test_alert_range_strings).isEmpty()) {
166             keywordList.add(res.getString(R.string.state_local_test_alert));
167         }
168 
169         raw[COLUMN_INDEX_RAW_KEYWORDS] = TextUtils.join(",", keywordList);
170 
171         raw[COLUMN_INDEX_RAW_SCREEN_TITLE] = res.getString(R.string.sms_cb_settings);
172         raw[COLUMN_INDEX_RAW_KEY] = CellBroadcastSettings.class.getSimpleName();
173         raw[COLUMN_INDEX_RAW_INTENT_ACTION] = Intent.ACTION_MAIN;
174         raw[COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE] = getContextMethod().getPackageName();
175         raw[COLUMN_INDEX_RAW_INTENT_TARGET_CLASS] = CellBroadcastSettings.class.getName();
176 
177         cursor.addRow(raw);
178         return cursor;
179     }
180 
181     @Override
queryNonIndexableKeys(String[] projection)182     public Cursor queryNonIndexableKeys(String[] projection) {
183         MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS);
184 
185         Resources res = getResourcesMethod();
186         Object[] ref;
187 
188         if (!res.getBoolean(R.bool.show_presidential_alerts_settings)) {
189             ref = new Object[1];
190             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
191                     CellBroadcastSettings.KEY_ENABLE_CMAS_PRESIDENTIAL_ALERTS;
192             cursor.addRow(ref);
193         }
194 
195         if (!CellBroadcastSettings.getResources(getContextMethod(),
196                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
197                 .getBoolean(R.bool.show_alert_speech_setting)) {
198             ref = new Object[1];
199             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
200                     CellBroadcastSettings.KEY_ENABLE_ALERT_SPEECH;
201             cursor.addRow(ref);
202         }
203 
204         if (!res.getBoolean(R.bool.show_extreme_alert_settings)) {
205             // Remove CMAS preference items in emergency alert category.
206             ref = new Object[1];
207             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
208                     CellBroadcastSettings.KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS;
209             cursor.addRow(ref);
210         }
211 
212         if (!res.getBoolean(R.bool.show_severe_alert_settings)) {
213 
214             ref = new Object[1];
215             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
216                     CellBroadcastSettings.KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS;
217             cursor.addRow(ref);
218         }
219 
220         if (!res.getBoolean(R.bool.show_amber_alert_settings)) {
221             ref = new Object[1];
222             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
223                     CellBroadcastSettings.KEY_ENABLE_CMAS_AMBER_ALERTS;
224             cursor.addRow(ref);
225         }
226 
227         if (!res.getBoolean(R.bool.config_showAreaUpdateInfoSettings)) {
228             ref = new Object[1];
229             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
230                     CellBroadcastSettings.KEY_ENABLE_AREA_UPDATE_INFO_ALERTS;
231             cursor.addRow(ref);
232         }
233 
234         CellBroadcastChannelManager channelManager = new CellBroadcastChannelManager(
235                 getContextMethod(), SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
236         if (channelManager.getCellBroadcastChannelRanges(
237                 R.array.cmas_amber_alerts_channels_range_strings).isEmpty()) {
238             ref = new Object[1];
239             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
240                     CellBroadcastSettings.KEY_ENABLE_CMAS_AMBER_ALERTS;
241             cursor.addRow(ref);
242         }
243 
244         if (channelManager.getCellBroadcastChannelRanges(
245                 R.array.emergency_alerts_channels_range_strings).isEmpty()) {
246             ref = new Object[1];
247             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
248                     CellBroadcastSettings.KEY_ENABLE_EMERGENCY_ALERTS;
249             cursor.addRow(ref);
250         }
251 
252         if (channelManager.getCellBroadcastChannelRanges(
253                 R.array.public_safety_messages_channels_range_strings).isEmpty()) {
254             ref = new Object[1];
255             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
256                     CellBroadcastSettings.KEY_ENABLE_PUBLIC_SAFETY_MESSAGES;
257             cursor.addRow(ref);
258         }
259 
260         if (channelManager.getCellBroadcastChannelRanges(
261                 R.array.state_local_test_alert_range_strings).isEmpty()) {
262             ref = new Object[1];
263             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
264                     CellBroadcastSettings.KEY_ENABLE_STATE_LOCAL_TEST_ALERTS;
265             cursor.addRow(ref);
266         }
267 
268         if (!isTestAlertsToggleVisible()) {
269             ref = new Object[1];
270             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
271                 CellBroadcastSettings.KEY_ENABLE_TEST_ALERTS;
272         }
273 
274         if (res.getString(R.string.emergency_alert_second_language_code).isEmpty()) {
275             ref = new Object[1];
276             ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] =
277                     CellBroadcastSettings.KEY_RECEIVE_CMAS_IN_SECOND_LANGUAGE;
278             cursor.addRow(ref);
279         }
280 
281         return cursor;
282     }
283 
284     /**
285      * Whether or not this is an Android Automotive platform.
286      * @return true if the current platform is automotive
287      */
288     @VisibleForTesting
isAutomotive()289     public boolean isAutomotive() {
290         return getContextMethod().getPackageManager().hasSystemFeature(
291                 PackageManager.FEATURE_AUTOMOTIVE);
292     }
293 
294     /**
295      * Check disable Cell Broadcast resource.
296      * @return true if Cell Broadcast disable configured by OEM.
297      */
298     @VisibleForTesting
isDisableAllCbMessages()299     public boolean isDisableAllCbMessages() {
300         boolean disable = false;
301         try {
302             Resources res = Resources.getSystem();
303             int id = res.getIdentifier("config_disable_all_cb_messages", "bool", "android");
304             disable = res.getBoolean(id);
305         } catch (Exception e) {
306             disable = false;
307         }
308         return disable;
309     }
310 }
311