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
This commit is contained in:
Fabrice Di Meglio
2014-06-06 16:31:45 -07:00
parent b76de1d4fa
commit dba577f8f0
4 changed files with 131 additions and 16 deletions

View File

@@ -469,7 +469,7 @@ public class SettingsActivity extends Activity
mIsShowingDashboard = (initialFragmentName == null); mIsShowingDashboard = (initialFragmentName == null);
if (mIsShowingDashboard) { if (mIsShowingDashboard) {
Index.getInstance(this).update(); Index.getInstance(getApplicationContext()).update();
} }
if (savedState != null) { if (savedState != null) {

View File

@@ -30,6 +30,7 @@ import android.content.res.Resources;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.nfc.NfcAdapter; import android.nfc.NfcAdapter;
import android.nfc.NfcManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.os.UserHandle; import android.os.UserHandle;
@@ -37,6 +38,7 @@ import android.preference.CheckBoxPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import android.provider.SearchIndexableResource;
import android.provider.Settings; import android.provider.Settings;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.text.TextUtils; import android.text.TextUtils;
@@ -47,11 +49,16 @@ import com.android.internal.telephony.SmsApplication.SmsApplicationData;
import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties; import com.android.internal.telephony.TelephonyProperties;
import com.android.settings.nfc.NfcEnabler; 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.Collection;
import java.util.List;
public class WirelessSettings extends RestrictedSettingsFragment public class WirelessSettings extends RestrictedSettingsFragment
implements OnPreferenceChangeListener { implements OnPreferenceChangeListener, Indexable {
private static final String TAG = "WirelessSettings"; private static final String TAG = "WirelessSettings";
private static final String KEY_TOGGLE_AIRPLANE = "toggle_airplane"; private static final String KEY_TOGGLE_AIRPLANE = "toggle_airplane";
@@ -270,7 +277,7 @@ public class WirelessSettings extends RestrictedSettingsFragment
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
//enable/disable wimax depending on the value in config.xml //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); com.android.internal.R.bool.config_wimaxEnabled);
if (!isWimaxEnabled) { if (!isWimaxEnabled) {
PreferenceScreen root = getPreferenceScreen(); PreferenceScreen root = getPreferenceScreen();
@@ -304,7 +311,7 @@ public class WirelessSettings extends RestrictedSettingsFragment
findPreference(KEY_ANDROID_BEAM_SETTINGS).setDependency(KEY_TOGGLE_AIRPLANE); findPreference(KEY_ANDROID_BEAM_SETTINGS).setDependency(KEY_TOGGLE_AIRPLANE);
} }
// Remove NFC if its not available // Remove NFC if not available
mNfcAdapter = NfcAdapter.getDefaultAdapter(activity); mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
if (mNfcAdapter == null) { if (mNfcAdapter == null) {
getPreferenceScreen().removePreference(nfc); getPreferenceScreen().removePreference(nfc);
@@ -319,7 +326,7 @@ public class WirelessSettings extends RestrictedSettingsFragment
} }
// Remove Mobile Network Settings and Manage Mobile Plan // Remove Mobile Network Settings and Manage Mobile Plan
// if config_show_mobile_plan sets false. // if config_show_mobile_plan sets false.
boolean isMobilePlanEnabled = this.getResources().getBoolean( final boolean isMobilePlanEnabled = this.getResources().getBoolean(
R.bool.config_show_mobile_plan); R.bool.config_show_mobile_plan);
if (!isMobilePlanEnabled) { if (!isMobilePlanEnabled) {
Preference pref = findPreference(KEY_MANAGE_MOBILE_PLAN); Preference pref = findPreference(KEY_MANAGE_MOBILE_PLAN);
@@ -342,14 +349,14 @@ public class WirelessSettings extends RestrictedSettingsFragment
// Enable Proxy selector settings if allowed. // Enable Proxy selector settings if allowed.
Preference mGlobalProxy = findPreference(KEY_PROXY_SETTINGS); Preference mGlobalProxy = findPreference(KEY_PROXY_SETTINGS);
DevicePolicyManager mDPM = (DevicePolicyManager) final DevicePolicyManager mDPM = (DevicePolicyManager)
activity.getSystemService(Context.DEVICE_POLICY_SERVICE); activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
// proxy UI disabled until we have better app support // proxy UI disabled until we have better app support
getPreferenceScreen().removePreference(mGlobalProxy); getPreferenceScreen().removePreference(mGlobalProxy);
mGlobalProxy.setEnabled(mDPM.getGlobalProxyAdmin() == null); mGlobalProxy.setEnabled(mDPM.getGlobalProxyAdmin() == null);
// Disable Tethering if it's not allowed or if it's a wifi-only device // 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); (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
if (isSecondaryUser || !cm.isTetheringSupported()) { if (isSecondaryUser || !cm.isTetheringSupported()) {
getPreferenceScreen().removePreference(findPreference(KEY_TETHER_SETTINGS)); getPreferenceScreen().removePreference(findPreference(KEY_TETHER_SETTINGS));
@@ -446,4 +453,103 @@ public class WirelessSettings extends RestrictedSettingsFragment
} }
return false; 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;
}
};
} }

View File

@@ -137,6 +137,8 @@ public class Index {
// Max number of proposed suggestions // Max number of proposed suggestions
private static final int MAX_PROPOSED_SUGGESTIONS = 5; 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 EMPTY = "";
private static final String NON_BREAKING_HYPHEN = "\u2011"; private static final String NON_BREAKING_HYPHEN = "\u2011";
private static final String HYPHEN = "-"; private static final String HYPHEN = "-";
@@ -150,11 +152,11 @@ public class Index {
private static final List<String> EMPTY_LIST = Collections.<String>emptyList(); private static final List<String> EMPTY_LIST = Collections.<String>emptyList();
private static Index sInstance; private static Index sInstance;
private final AtomicBoolean mIsAvailable = new AtomicBoolean(false); private final AtomicBoolean mIsAvailable = new AtomicBoolean(false);
private final UpdateData mDataToProcess = new UpdateData(); private final UpdateData mDataToProcess = new UpdateData();
private Context mContext; private Context mContext;
private final String mBaseAuthority;
/** /**
* A private class to describe the update data for the Index database * A private class to describe the update data for the Index database
@@ -185,15 +187,16 @@ public class Index {
*/ */
public static Index getInstance(Context context) { public static Index getInstance(Context context) {
if (sInstance == null) { if (sInstance == null) {
sInstance = new Index(context); sInstance = new Index(context, BASE_AUTHORITY);
} else { } else {
sInstance.setContext(context); sInstance.setContext(context);
} }
return sInstance; return sInstance;
} }
public Index(Context context) { public Index(Context context, String baseAuthority) {
mContext = context; mContext = context;
mBaseAuthority = baseAuthority;
} }
public void setContext(Context context) { public void setContext(Context context) {
@@ -281,14 +284,15 @@ public class Index {
try { try {
final int baseRank = Ranking.getBaseRankForAuthority(authority); 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); final Uri uriForResources = buildUriForXmlResources(authority);
addIndexablesForXmlResourceUri(packageContext, packageName, uriForResources, addIndexablesForXmlResourceUri(context, packageName, uriForResources,
SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS, baseRank); SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS, baseRank);
final Uri uriForRawData = buildUriForRawData(authority); final Uri uriForRawData = buildUriForRawData(authority);
addIndexablesForRawDataUri(packageContext, packageName, uriForRawData, addIndexablesForRawDataUri(context, packageName, uriForRawData,
SearchIndexablesContract.INDEXABLES_RAW_COLUMNS, baseRank); SearchIndexablesContract.INDEXABLES_RAW_COLUMNS, baseRank);
return true; return true;
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
@@ -1139,7 +1143,12 @@ public class Index {
final int count = dataToUpdate.size(); final int count = dataToUpdate.size();
for (int n = 0; n < count; n++) { for (int n = 0; n < count; n++) {
final SearchIndexableData data = dataToUpdate.get(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(); final long now = System.currentTimeMillis();

View File

@@ -87,9 +87,9 @@ public final class SearchIndexableResources {
sResMap.put(WirelessSettings.class.getName(), sResMap.put(WirelessSettings.class.getName(),
new SearchIndexableResource( new SearchIndexableResource(
Ranking.getRankForClassName(WirelessSettings.class.getName()), Ranking.getRankForClassName(WirelessSettings.class.getName()),
R.xml.wireless_settings, NO_DATA_RES_ID,
WirelessSettings.class.getName(), WirelessSettings.class.getName(),
R.drawable.empty_icon)); R.drawable.ic_settings_more));
sResMap.put(HomeSettings.class.getName(), sResMap.put(HomeSettings.class.getName(),
new SearchIndexableResource( new SearchIndexableResource(