Fix bug #15460001 "Cell broadcasts" setting search suggested in wifi only device though setting is not present

- implement a BaseSearchIndexProvider for WirelessSettings
- fix Context passed to the Index: now use an ApplicationContext
- also use the correct Context when dealing with Settings SearchIndexProvider
- also makes impossible a rogue BaseSearchIndexProvider to crash Settings
if not well behaving
- last, fix icon used for "NFC & more" search results

Change-Id: I8b5cc999fa57a9e1977ee57394801d54cf3dbabb
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 6ba79cc..0e2af0e 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -469,7 +469,7 @@
         mIsShowingDashboard = (initialFragmentName == null);
 
         if (mIsShowingDashboard) {
-            Index.getInstance(this).update();
+            Index.getInstance(getApplicationContext()).update();
         }
 
         if (savedState != null) {
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index fd2e945..7aaa0a6 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -30,6 +30,7 @@
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.nfc.NfcAdapter;
+import android.nfc.NfcManager;
 import android.os.Bundle;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -37,6 +38,7 @@
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceChangeListener;
 import android.preference.PreferenceScreen;
+import android.provider.SearchIndexableResource;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -47,11 +49,16 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.settings.nfc.NfcEnabler;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 
 public class WirelessSettings extends RestrictedSettingsFragment
-        implements OnPreferenceChangeListener {
+        implements OnPreferenceChangeListener, Indexable {
     private static final String TAG = "WirelessSettings";
 
     private static final String KEY_TOGGLE_AIRPLANE = "toggle_airplane";
@@ -270,7 +277,7 @@
                 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
 
         //enable/disable wimax depending on the value in config.xml
-        boolean isWimaxEnabled = !isSecondaryUser && this.getResources().getBoolean(
+        final boolean isWimaxEnabled = !isSecondaryUser && this.getResources().getBoolean(
                 com.android.internal.R.bool.config_wimaxEnabled);
         if (!isWimaxEnabled) {
             PreferenceScreen root = getPreferenceScreen();
@@ -304,7 +311,7 @@
             findPreference(KEY_ANDROID_BEAM_SETTINGS).setDependency(KEY_TOGGLE_AIRPLANE);
         }
 
-        // Remove NFC if its not available
+        // Remove NFC if not available
         mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
         if (mNfcAdapter == null) {
             getPreferenceScreen().removePreference(nfc);
@@ -319,7 +326,7 @@
         }
         // Remove Mobile Network Settings and Manage Mobile Plan
         // if config_show_mobile_plan sets false.
-        boolean isMobilePlanEnabled = this.getResources().getBoolean(
+        final boolean isMobilePlanEnabled = this.getResources().getBoolean(
                 R.bool.config_show_mobile_plan);
         if (!isMobilePlanEnabled) {
             Preference pref = findPreference(KEY_MANAGE_MOBILE_PLAN);
@@ -342,14 +349,14 @@
 
         // Enable Proxy selector settings if allowed.
         Preference mGlobalProxy = findPreference(KEY_PROXY_SETTINGS);
-        DevicePolicyManager mDPM = (DevicePolicyManager)
+        final DevicePolicyManager mDPM = (DevicePolicyManager)
                 activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
         // proxy UI disabled until we have better app support
         getPreferenceScreen().removePreference(mGlobalProxy);
         mGlobalProxy.setEnabled(mDPM.getGlobalProxyAdmin() == null);
 
         // Disable Tethering if it's not allowed or if it's a wifi-only device
-        ConnectivityManager cm =
+        final ConnectivityManager cm =
                 (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
         if (isSecondaryUser || !cm.isTetheringSupported()) {
             getPreferenceScreen().removePreference(findPreference(KEY_TETHER_SETTINGS));
@@ -446,4 +453,103 @@
         }
         return false;
     }
+
+    /**
+     * For Search.
+     */
+    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+        new BaseSearchIndexProvider() {
+            @Override
+            public List<SearchIndexableResource> getXmlResourcesToIndex(
+                    Context context, boolean enabled) {
+                SearchIndexableResource sir = new SearchIndexableResource(context);
+                sir.xmlResId = R.xml.wireless_settings;
+                return Arrays.asList(sir);
+            }
+
+            @Override
+            public List<String> getNonIndexableKeys(Context context) {
+                final ArrayList<String> result = new ArrayList<String>();
+
+                result.add(KEY_TOGGLE_NSD);
+
+                final boolean isSecondaryUser = UserHandle.myUserId() != UserHandle.USER_OWNER;
+                final boolean isWimaxEnabled = !isSecondaryUser && context.getResources().getBoolean(
+                        com.android.internal.R.bool.config_wimaxEnabled);
+                if (!isWimaxEnabled) {
+                    result.add(KEY_WIMAX_SETTINGS);
+                }
+
+                if (isSecondaryUser) { // Disable VPN
+                    result.add(KEY_VPN_SETTINGS);
+                }
+
+                // Remove NFC if not available
+                final NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
+                if (manager != null) {
+                    NfcAdapter adapter = manager.getDefaultAdapter();
+                    if (adapter == null) {
+                        result.add(KEY_TOGGLE_NFC);
+                        result.add(KEY_ANDROID_BEAM_SETTINGS);
+                    }
+                }
+
+                // Remove Mobile Network Settings and Manage Mobile Plan if it's a wifi-only device.
+                if (isSecondaryUser || Utils.isWifiOnly(context)) {
+                    result.add(KEY_MOBILE_NETWORK_SETTINGS);
+                    result.add(KEY_MANAGE_MOBILE_PLAN);
+                }
+
+                // Remove Mobile Network Settings and Manage Mobile Plan
+                // if config_show_mobile_plan sets false.
+                final boolean isMobilePlanEnabled = context.getResources().getBoolean(
+                        R.bool.config_show_mobile_plan);
+                if (!isMobilePlanEnabled) {
+                    result.add(KEY_MANAGE_MOBILE_PLAN);
+                }
+
+                // Remove SMS Application if the device does not support SMS
+                TelephonyManager tm =
+                        (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+                if (!tm.isSmsCapable()) {
+                    result.add(KEY_SMS_APPLICATION);
+                }
+
+                final PackageManager pm = context.getPackageManager();
+
+                // Remove Airplane Mode settings if it's a stationary device such as a TV.
+                if (pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)) {
+                    result.add(KEY_TOGGLE_AIRPLANE);
+                }
+
+                // proxy UI disabled until we have better app support
+                result.add(KEY_PROXY_SETTINGS);
+
+                // Disable Tethering if it's not allowed or if it's a wifi-only device
+                ConnectivityManager cm =
+                        (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+                if (isSecondaryUser || !cm.isTetheringSupported()) {
+                    result.add(KEY_TETHER_SETTINGS);
+                }
+
+                // Enable link to CMAS app settings depending on the value in config.xml.
+                boolean isCellBroadcastAppLinkEnabled = context.getResources().getBoolean(
+                        com.android.internal.R.bool.config_cellBroadcastAppLinks);
+                try {
+                    if (isCellBroadcastAppLinkEnabled) {
+                        if (pm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
+                                == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+                            isCellBroadcastAppLinkEnabled = false;  // CMAS app disabled
+                        }
+                    }
+                } catch (IllegalArgumentException ignored) {
+                    isCellBroadcastAppLinkEnabled = false;  // CMAS app not installed
+                }
+                if (isSecondaryUser || !isCellBroadcastAppLinkEnabled) {
+                    result.add(KEY_CELL_BROADCAST_SETTINGS);
+                }
+
+                return result;
+            }
+        };
 }
diff --git a/src/com/android/settings/search/Index.java b/src/com/android/settings/search/Index.java
index 8ed6074..bcc6ca4 100644
--- a/src/com/android/settings/search/Index.java
+++ b/src/com/android/settings/search/Index.java
@@ -137,6 +137,8 @@
     // Max number of proposed suggestions
     private static final int MAX_PROPOSED_SUGGESTIONS = 5;
 
+    private static final String BASE_AUTHORITY = "com.android.settings";
+
     private static final String EMPTY = "";
     private static final String NON_BREAKING_HYPHEN = "\u2011";
     private static final String HYPHEN = "-";
@@ -150,11 +152,11 @@
 
     private static final List<String> EMPTY_LIST = Collections.<String>emptyList();
 
-
     private static Index sInstance;
     private final AtomicBoolean mIsAvailable = new AtomicBoolean(false);
     private final UpdateData mDataToProcess = new UpdateData();
     private Context mContext;
+    private final String mBaseAuthority;
 
     /**
      * A private class to describe the update data for the Index database
@@ -185,15 +187,16 @@
      */
     public static Index getInstance(Context context) {
         if (sInstance == null) {
-            sInstance = new Index(context);
+            sInstance = new Index(context, BASE_AUTHORITY);
         } else {
             sInstance.setContext(context);
         }
         return sInstance;
     }
 
-    public Index(Context context) {
+    public Index(Context context, String baseAuthority) {
         mContext = context;
+        mBaseAuthority = baseAuthority;
     }
 
     public void setContext(Context context) {
@@ -281,14 +284,15 @@
         try {
             final int baseRank = Ranking.getBaseRankForAuthority(authority);
 
-            final Context packageContext = mContext.createPackageContext(packageName, 0);
+            final Context context = mBaseAuthority.equals(authority) ?
+                    mContext : mContext.createPackageContext(packageName, 0);
 
             final Uri uriForResources = buildUriForXmlResources(authority);
-            addIndexablesForXmlResourceUri(packageContext, packageName, uriForResources,
+            addIndexablesForXmlResourceUri(context, packageName, uriForResources,
                     SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS, baseRank);
 
             final Uri uriForRawData = buildUriForRawData(authority);
-            addIndexablesForRawDataUri(packageContext, packageName, uriForRawData,
+            addIndexablesForRawDataUri(context, packageName, uriForRawData,
                     SearchIndexablesContract.INDEXABLES_RAW_COLUMNS, baseRank);
             return true;
         } catch (PackageManager.NameNotFoundException e) {
@@ -1139,7 +1143,12 @@
             final int count = dataToUpdate.size();
             for (int n = 0; n < count; n++) {
                 final SearchIndexableData data = dataToUpdate.get(n);
-                indexOneSearchIndexableData(database, localeStr, data, nonIndexableKeys);
+                try {
+                    indexOneSearchIndexableData(database, localeStr, data, nonIndexableKeys);
+                } catch (Exception e) {
+                    Log.e(LOG_TAG,
+                            "Cannot index: " + data.className + " for locale: " + localeStr, e);
+                }
             }
 
             final long now = System.currentTimeMillis();
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 01d3c07..7c96a4a 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -87,9 +87,9 @@
         sResMap.put(WirelessSettings.class.getName(),
                 new SearchIndexableResource(
                         Ranking.getRankForClassName(WirelessSettings.class.getName()),
-                        R.xml.wireless_settings,
+                        NO_DATA_RES_ID,
                         WirelessSettings.class.getName(),
-                        R.drawable.empty_icon));
+                        R.drawable.ic_settings_more));
 
         sResMap.put(HomeSettings.class.getName(),
                 new SearchIndexableResource(