2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings;
19 import android.app.Activity;
20 import android.content.ClipData;
21 import android.content.ClipboardManager;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.pm.ApplicationInfo;
25 import android.content.pm.PackageInfo;
26 import android.content.pm.PackageManager;
27 import android.content.pm.PackageManager.NameNotFoundException;
28 import android.content.pm.ResolveInfo;
29 import android.os.Build;
30 import android.os.Bundle;
31 import android.os.PersistableBundle;
32 import android.os.SELinux;
33 import android.os.SystemClock;
34 import android.os.SystemProperties;
35 import android.os.UserHandle;
36 import android.os.UserManager;
37 import android.preference.Preference;
38 import android.preference.PreferenceGroup;
39 import android.preference.PreferenceScreen;
40 import android.provider.SearchIndexableResource;
41 import android.provider.Settings;
42 import android.telephony.CarrierConfigManager;
43 import android.text.TextUtils;
44 import android.text.format.DateFormat;
45 import android.util.Log;
46 import android.widget.Toast;
48 import cyanogenmod.hardware.CMHardwareManager;
49 import com.android.internal.logging.MetricsLogger;
50 import com.android.settings.search.BaseSearchIndexProvider;
51 import com.android.settings.search.Index;
52 import com.android.settings.search.Indexable;
54 import java.io.BufferedReader;
55 import java.io.FileReader;
56 import java.io.IOException;
57 import java.text.ParseException;
58 import java.text.SimpleDateFormat;
59 import java.util.ArrayList;
60 import java.util.Arrays;
61 import java.util.Date;
62 import java.util.List;
63 import java.util.Locale;
64 import java.util.regex.Matcher;
65 import java.util.regex.Pattern;
67 public class DeviceInfoSettings extends SettingsPreferenceFragment implements Indexable {
69 private static final String LOG_TAG = "DeviceInfoSettings";
70 private static final String FILENAME_PROC_VERSION = "/proc/version";
71 private static final String FILENAME_MSV = "/sys/board_properties/soc/msv";
73 private static final String KEY_MANUAL = "manual";
74 private static final String KEY_REGULATORY_INFO = "regulatory_info";
75 private static final String KEY_SYSTEM_UPDATE_SETTINGS = "system_update_settings";
76 private static final String PROPERTY_URL_SAFETYLEGAL = "ro.url.safetylegal";
77 private static final String PROPERTY_SELINUX_STATUS = "ro.build.selinux";
78 private static final String KEY_KERNEL_VERSION = "kernel_version";
79 private static final String KEY_BUILD_NUMBER = "build_number";
80 private static final String KEY_DEVICE_MODEL = "device_model";
81 private static final String KEY_DEVICE_NAME = "device_name";
82 private static final String KEY_SELINUX_STATUS = "selinux_status";
83 private static final String KEY_BASEBAND_VERSION = "baseband_version";
84 private static final String KEY_FIRMWARE_VERSION = "firmware_version";
85 private static final String KEY_SECURITY_PATCH = "security_patch";
86 private static final String KEY_UPDATE_SETTING = "additional_system_update_settings";
87 private static final String KEY_EQUIPMENT_ID = "fcc_equipment_id";
88 private static final String PROPERTY_EQUIPMENT_ID = "ro.ril.fccid";
89 private static final String KEY_DEVICE_FEEDBACK = "device_feedback";
90 private static final String KEY_SAFETY_LEGAL = "safetylegal";
91 private static final String KEY_MOD_VERSION = "mod_version";
92 private static final String KEY_MOD_BUILD_DATE = "build_date";
93 private static final String KEY_MOD_API_LEVEL = "mod_api_level";
94 private static final String KEY_CM_UPDATES = "cm_updates";
96 static final int TAPS_TO_BE_A_DEVELOPER = 7;
97 static final int TAPS_TO_SHOW_DEVICEID = 7;
99 long[] mHits = new long[3];
100 int mDevHitCountdown;
106 protected int getMetricsCategory() {
107 return MetricsLogger.DEVICEINFO;
111 protected int getHelpResource() {
112 return R.string.help_uri_about;
116 public void onCreate(Bundle icicle) {
117 super.onCreate(icicle);
119 addPreferencesFromResource(R.xml.device_info_settings);
121 setStringSummary(KEY_FIRMWARE_VERSION, Build.VERSION.RELEASE);
122 findPreference(KEY_FIRMWARE_VERSION).setEnabled(true);
123 String patch = Build.VERSION.SECURITY_PATCH;
124 if (!"".equals(patch)) {
126 SimpleDateFormat template = new SimpleDateFormat("yyyy-MM-dd");
127 Date patchDate = template.parse(patch);
128 String format = DateFormat.getBestDateTimePattern(Locale.getDefault(), "dMMMMyyyy");
129 patch = DateFormat.format(format, patchDate).toString();
130 } catch (ParseException e) {
131 // broken parse; fall through and use the raw string
133 setStringSummary(KEY_SECURITY_PATCH, patch);
135 getPreferenceScreen().removePreference(findPreference(KEY_SECURITY_PATCH));
138 setValueSummary(KEY_BASEBAND_VERSION, "gsm.version.baseband");
139 setValueSummary(KEY_EQUIPMENT_ID, PROPERTY_EQUIPMENT_ID);
140 setStringSummary(KEY_DEVICE_MODEL, Build.MODEL);
141 setStringSummary(KEY_BUILD_NUMBER, Build.DISPLAY);
142 findPreference(KEY_BUILD_NUMBER).setEnabled(true);
144 final Preference kernelPref = findPreference(KEY_KERNEL_VERSION);
145 kernelPref.setEnabled(true);
146 kernelPref.setSummary(getFormattedKernelVersion());
147 findPreference(KEY_MOD_VERSION).setSummary(
148 cyanogenmod.os.Build.CYANOGENMOD_DISPLAY_VERSION);
149 findPreference(KEY_MOD_VERSION).setEnabled(true);
150 setValueSummary(KEY_MOD_BUILD_DATE, "ro.build.date");
151 setExplicitValueSummary(KEY_MOD_API_LEVEL, constructApiLevelString());
152 findPreference(KEY_MOD_API_LEVEL).setEnabled(true);
153 findPreference(KEY_MOD_BUILD_DATE).setEnabled(true);
155 if (!SELinux.isSELinuxEnabled()) {
156 String status = getResources().getString(R.string.selinux_status_disabled);
157 setStringSummary(KEY_SELINUX_STATUS, status);
158 } else if (!SELinux.isSELinuxEnforced()) {
159 String status = getResources().getString(R.string.selinux_status_permissive);
160 setStringSummary(KEY_SELINUX_STATUS, status);
163 setStringSummary(KEY_DEVICE_NAME, Build.PRODUCT);
164 removePreferenceIfBoolFalse(KEY_DEVICE_NAME, R.bool.config_displayDeviceName);
166 // Remove selinux information if property is not present
167 removePreferenceIfPropertyMissing(getPreferenceScreen(), KEY_SELINUX_STATUS,
168 PROPERTY_SELINUX_STATUS);
170 // Only the owner should see the Updater settings, if it exists
171 if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
172 removePreferenceIfPackageNotInstalled(findPreference(KEY_CM_UPDATES));
174 getPreferenceScreen().removePreference(findPreference(KEY_CM_UPDATES));
177 // Remove Safety information preference if PROPERTY_URL_SAFETYLEGAL is not set
178 removePreferenceIfPropertyMissing(getPreferenceScreen(), KEY_SAFETY_LEGAL,
179 PROPERTY_URL_SAFETYLEGAL);
181 // Remove Equipment id preference if FCC ID is not set by RIL
182 removePreferenceIfPropertyMissing(getPreferenceScreen(), KEY_EQUIPMENT_ID,
183 PROPERTY_EQUIPMENT_ID);
185 // Remove Baseband version if wifi-only device
186 if (Utils.isWifiOnly(getActivity())) {
187 getPreferenceScreen().removePreference(findPreference(KEY_BASEBAND_VERSION));
190 // Dont show feedback option if there is no reporter.
191 if (TextUtils.isEmpty(getFeedbackReporterPackage(getActivity()))) {
192 getPreferenceScreen().removePreference(findPreference(KEY_DEVICE_FEEDBACK));
196 * Settings is a generic app and should not contain any device-specific
199 final Activity act = getActivity();
201 // These are contained by the root preference screen
202 PreferenceGroup parentPreference = getPreferenceScreen();
203 if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
204 Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference,
205 KEY_SYSTEM_UPDATE_SETTINGS,
206 Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
207 /* Make sure the activity is provided by who we want... */
208 if (findPreference(KEY_SYSTEM_UPDATE_SETTINGS) != null)
209 removePreferenceIfPackageNotInstalled(findPreference(KEY_SYSTEM_UPDATE_SETTINGS));
211 // Remove for secondary users
212 removePreference(KEY_SYSTEM_UPDATE_SETTINGS);
215 // Read platform settings for additional system update setting
216 removePreferenceIfBoolFalse(KEY_UPDATE_SETTING,
217 R.bool.config_additional_system_update_setting_enable);
219 // Remove manual entry if none present.
220 removePreferenceIfBoolFalse(KEY_MANUAL, R.bool.config_show_manual);
222 // Remove regulatory information if none present
223 final Intent intent = new Intent(Settings.ACTION_SHOW_REGULATORY_INFO);
224 if (getPackageManager().queryIntentActivities(intent, 0).isEmpty()) {
225 Preference pref = findPreference(KEY_REGULATORY_INFO);
227 getPreferenceScreen().removePreference(pref);
233 public void onResume() {
235 mDevHitCountdown = getActivity().getSharedPreferences(DevelopmentSettings.PREF_FILE,
236 Context.MODE_PRIVATE).getBoolean(DevelopmentSettings.PREF_SHOW,
237 android.os.Build.TYPE.equals("eng")) ? -1 : TAPS_TO_BE_A_DEVELOPER;
239 mDevIdCountdown = TAPS_TO_SHOW_DEVICEID;
244 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
245 if (preference.getKey().equals(KEY_FIRMWARE_VERSION)) {
246 System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);
247 mHits[mHits.length-1] = SystemClock.uptimeMillis();
248 if (mHits[0] >= (SystemClock.uptimeMillis()-500)) {
249 UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
250 if (um.hasUserRestriction(UserManager.DISALLOW_FUN)) {
251 Log.d(LOG_TAG, "Sorry, no fun for you!");
255 Intent intent = new Intent(Intent.ACTION_MAIN);
256 intent.setClassName("android",
257 com.android.internal.app.PlatLogoActivity.class.getName());
259 startActivity(intent);
260 } catch (Exception e) {
261 Log.e(LOG_TAG, "Unable to start activity " + intent.toString());
264 } else if (preference.getKey().equals(KEY_MOD_BUILD_DATE)) {
265 System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);
266 mHits[mHits.length-1] = SystemClock.uptimeMillis();
267 if (mHits[0] >= (SystemClock.uptimeMillis()-500)) {
268 Intent intent = new Intent();
269 intent.setClassName("com.android.systemui",
270 "com.android.systemui.tuner.TunerActivity$DemoModeActivity");
272 startActivity(intent);
273 } catch (Exception e) {
274 Log.e(LOG_TAG, "Unable to start activity " + intent.toString());
277 } else if (preference.getKey().equals(KEY_KERNEL_VERSION)) {
280 if (mDevIdCountdown == 0) {
281 final CMHardwareManager hwMgr = CMHardwareManager.getInstance(getActivity().getApplicationContext());
282 final String deviceID = hwMgr.getUniqueDeviceId();
284 if (deviceID == null) {
285 msg = getText(R.string.show_device_id_failed_cm);
288 final ClipboardManager clipboardMgr = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
289 clipboardMgr.setPrimaryClip(ClipData.newPlainText(getResources().
290 getString(R.string.show_device_id_clipboard_label),
292 msg = getResources().getString(
293 R.string.show_device_id_copied_cm, deviceID);
296 mDevIdToast = Toast.makeText(getActivity(), msg,
299 mDevIdCountdown = TAPS_TO_SHOW_DEVICEID;
301 else if (mDevIdCountdown > 0
302 && mDevIdCountdown < (TAPS_TO_SHOW_DEVICEID-2)) {
304 if (mDevIdToast != null) {
305 mDevIdToast.cancel();
307 mDevIdToast = Toast.makeText(getActivity(), getResources().getQuantityString(
308 R.plurals.show_device_id_countdown_cm, mDevIdCountdown, mDevIdCountdown),
313 } else if (preference.getKey().equals(KEY_BUILD_NUMBER)) {
314 // Don't enable developer options for secondary users.
315 if (UserHandle.myUserId() != UserHandle.USER_OWNER) return true;
317 // Don't enable developer options until device has been provisioned
318 if (Settings.Global.getInt(getActivity().getContentResolver(),
319 Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
323 final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
324 if (um.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES)) return true;
326 if (mDevHitCountdown > 0) {
328 if (mDevHitCountdown == 0) {
329 getActivity().getSharedPreferences(DevelopmentSettings.PREF_FILE,
330 Context.MODE_PRIVATE).edit().putBoolean(
331 DevelopmentSettings.PREF_SHOW, true).apply();
332 if (mDevHitToast != null) {
333 mDevHitToast.cancel();
335 mDevHitToast = Toast.makeText(getActivity(), R.string.show_dev_on_cm,
338 // This is good time to index the Developer Options
340 getActivity().getApplicationContext()).updateFromClassNameResource(
341 DevelopmentSettings.class.getName(), true, true);
343 } else if (mDevHitCountdown > 0
344 && mDevHitCountdown < (TAPS_TO_BE_A_DEVELOPER-2)) {
345 if (mDevHitToast != null) {
346 mDevHitToast.cancel();
348 mDevHitToast = Toast.makeText(getActivity(), getResources().getQuantityString(
349 R.plurals.show_dev_countdown_cm, mDevHitCountdown, mDevHitCountdown),
353 } else if (mDevHitCountdown < 0) {
354 if (mDevHitToast != null) {
355 mDevHitToast.cancel();
357 mDevHitToast = Toast.makeText(getActivity(), R.string.show_dev_already_cm,
361 } else if (preference.getKey().equals(KEY_DEVICE_FEEDBACK)) {
363 } else if(preference.getKey().equals(KEY_SYSTEM_UPDATE_SETTINGS)) {
364 CarrierConfigManager configManager =
365 (CarrierConfigManager) getSystemService(Context.CARRIER_CONFIG_SERVICE);
366 PersistableBundle b = configManager.getConfig();
367 if (b.getBoolean(CarrierConfigManager.KEY_CI_ACTION_ON_SYS_UPDATE_BOOL)) {
368 ciActionOnSysUpdate(b);
370 } else if (preference.getKey().equals(KEY_MOD_VERSION)) {
371 System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);
372 mHits[mHits.length-1] = SystemClock.uptimeMillis();
373 if (mHits[0] >= (SystemClock.uptimeMillis()-500)) {
374 Intent intent = new Intent(Intent.ACTION_MAIN);
375 intent.putExtra("is_cm", true);
376 intent.setClassName("android",
377 com.android.internal.app.PlatLogoActivity.class.getName());
379 startActivity(intent);
380 } catch (Exception e) {
381 Log.e(LOG_TAG, "Unable to start activity " + intent.toString());
385 return super.onPreferenceTreeClick(preferenceScreen, preference);
389 * Trigger client initiated action (send intent) on system update
391 private void ciActionOnSysUpdate(PersistableBundle b) {
392 String intentStr = b.getString(CarrierConfigManager.
393 KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING);
394 if (!TextUtils.isEmpty(intentStr)) {
395 String extra = b.getString(CarrierConfigManager.
396 KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING);
397 String extraVal = b.getString(CarrierConfigManager.
398 KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING);
400 Intent intent = new Intent(intentStr);
401 if (!TextUtils.isEmpty(extra)) {
402 intent.putExtra(extra, extraVal);
404 Log.d(LOG_TAG, "ciActionOnSysUpdate: broadcasting intent " + intentStr +
405 " with extra " + extra + ", " + extraVal);
406 getActivity().getApplicationContext().sendBroadcast(intent);
410 private void removePreferenceIfPropertyMissing(PreferenceGroup preferenceGroup,
411 String preference, String property ) {
412 if (SystemProperties.get(property).equals("")) {
413 // Property is missing so remove preference from group
415 preferenceGroup.removePreference(findPreference(preference));
416 } catch (RuntimeException e) {
417 Log.d(LOG_TAG, "Property '" + property + "' missing and no '"
418 + preference + "' preference");
423 private void removePreferenceIfBoolFalse(String preference, int resId) {
424 if (!getResources().getBoolean(resId)) {
425 Preference pref = findPreference(preference);
427 getPreferenceScreen().removePreference(pref);
432 private void setStringSummary(String preference, String value) {
434 findPreference(preference).setSummary(value);
435 } catch (RuntimeException e) {
436 findPreference(preference).setSummary(
437 getResources().getString(R.string.device_info_default));
441 private void setValueSummary(String preference, String property) {
443 findPreference(preference).setSummary(
444 SystemProperties.get(property,
445 getResources().getString(R.string.device_info_default)));
446 } catch (RuntimeException e) {
451 private void setExplicitValueSummary(String preference, String value) {
453 findPreference(preference).setSummary(value);
454 } catch (RuntimeException e) {
459 private void sendFeedback() {
460 String reporterPackage = getFeedbackReporterPackage(getActivity());
461 if (TextUtils.isEmpty(reporterPackage)) {
464 Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
465 intent.setPackage(reporterPackage);
466 startActivityForResult(intent, 0);
470 * Reads a line from the specified file.
471 * @param filename the file to read from
472 * @return the first line, if any.
473 * @throws IOException if the file couldn't be read
475 private static String readLine(String filename) throws IOException {
476 BufferedReader reader = new BufferedReader(new FileReader(filename), 256);
478 return reader.readLine();
484 public static String getFormattedKernelVersion() {
486 return formatKernelVersion(readLine(FILENAME_PROC_VERSION));
488 } catch (IOException e) {
490 "IO Exception when getting kernel version for Device Info screen",
493 return "Unavailable";
497 private static String constructApiLevelString() {
498 int sdkInt = cyanogenmod.os.Build.CM_VERSION.SDK_INT;
499 StringBuilder builder = new StringBuilder();
500 builder.append(cyanogenmod.os.Build.getNameForSDKInt(sdkInt))
501 .append(" (" + sdkInt + ")");
502 return builder.toString();
505 public static String formatKernelVersion(String rawKernelVersion) {
506 // Example (see tests for more):
507 // Linux version 3.0.31-g6fb96c9 (android-build@xxx.xxx.xxx.xxx.com) \
508 // (gcc version 4.6.x-xxx 20120106 (prerelease) (GCC) ) #1 SMP PREEMPT \
509 // Thu Jun 28 11:02:39 PDT 2012
511 final String PROC_VERSION_REGEX =
512 "Linux version (\\S+) " + /* group 1: "3.0.31-g6fb96c9" */
513 "\\((\\S+?)\\) " + /* group 2: "x@y.com" (kernel builder) */
514 "(?:\\(gcc.+? \\)) " + /* ignore: GCC version information */
515 "(#\\d+) " + /* group 3: "#1" */
516 "(?:.*?)?" + /* ignore: optional SMP, PREEMPT, and any CONFIG_FLAGS */
517 "((Sun|Mon|Tue|Wed|Thu|Fri|Sat).+)"; /* group 4: "Thu Jun 28 11:02:39 PDT 2012" */
519 Matcher m = Pattern.compile(PROC_VERSION_REGEX).matcher(rawKernelVersion);
521 Log.e(LOG_TAG, "Regex did not match on /proc/version: " + rawKernelVersion);
522 return "Unavailable";
523 } else if (m.groupCount() < 4) {
524 Log.e(LOG_TAG, "Regex match on /proc/version only returned " + m.groupCount()
526 return "Unavailable";
528 return m.group(1) + "\n" + // 3.0.31-g6fb96c9
529 m.group(2) + " " + m.group(3) + "\n" + // x@y.com #1
530 m.group(4); // Thu Jun 28 11:02:39 PDT 2012
534 * Returns " (ENGINEERING)" if the msv file has a zero value, else returns "".
535 * @return a string to append to the model number description.
537 private String getMsvSuffix() {
538 // Production devices should have a non-zero value. If we can't read it, assume it's a
539 // production device so that we don't accidentally show that it's an ENGINEERING device.
541 String msv = readLine(FILENAME_MSV);
542 // Parse as a hex number. If it evaluates to a zero, then it's an engineering build.
543 if (Long.parseLong(msv, 16) == 0) {
544 return " (ENGINEERING)";
546 } catch (IOException ioe) {
547 // Fail quietly, as the file may not exist on some devices.
548 } catch (NumberFormatException nfe) {
549 // Fail quietly, returning empty string should be sufficient
554 private static String getFeedbackReporterPackage(Context context) {
555 final String feedbackReporter =
556 context.getResources().getString(R.string.oem_preferred_feedback_reporter);
557 if (TextUtils.isEmpty(feedbackReporter)) {
558 // Reporter not configured. Return.
559 return feedbackReporter;
561 // Additional checks to ensure the reporter is on system image, and reporter is
562 // configured to listen to the intent. Otherwise, dont show the "send feedback" option.
563 final Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
565 PackageManager pm = context.getPackageManager();
566 List<ResolveInfo> resolvedPackages =
567 pm.queryIntentActivities(intent, PackageManager.GET_RESOLVED_FILTER);
568 for (ResolveInfo info : resolvedPackages) {
569 if (info.activityInfo != null) {
570 if (!TextUtils.isEmpty(info.activityInfo.packageName)) {
572 ApplicationInfo ai = pm.getApplicationInfo(info.activityInfo.packageName, 0);
573 if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
574 // Package is on the system image
575 if (TextUtils.equals(
576 info.activityInfo.packageName, feedbackReporter)) {
577 return feedbackReporter;
580 } catch (PackageManager.NameNotFoundException e) {
581 // No need to do anything here.
592 public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
593 new BaseSearchIndexProvider() {
596 public List<SearchIndexableResource> getXmlResourcesToIndex(
597 Context context, boolean enabled) {
598 final SearchIndexableResource sir = new SearchIndexableResource(context);
599 sir.xmlResId = R.xml.device_info_settings;
600 return Arrays.asList(sir);
604 public List<String> getNonIndexableKeys(Context context) {
605 final List<String> keys = new ArrayList<String>();
606 if (isPropertyMissing(PROPERTY_SELINUX_STATUS)) {
607 keys.add(KEY_SELINUX_STATUS);
609 if (isPropertyMissing(PROPERTY_URL_SAFETYLEGAL)) {
610 keys.add(KEY_SAFETY_LEGAL);
612 if (isPropertyMissing(PROPERTY_EQUIPMENT_ID)) {
613 keys.add(KEY_EQUIPMENT_ID);
615 // Remove Baseband version if wifi-only device
616 if (Utils.isWifiOnly(context)) {
617 keys.add((KEY_BASEBAND_VERSION));
619 // Dont show feedback option if there is no reporter.
620 if (TextUtils.isEmpty(getFeedbackReporterPackage(context))) {
621 keys.add(KEY_DEVICE_FEEDBACK);
623 if (UserHandle.myUserId() != UserHandle.USER_OWNER) {
624 keys.add(KEY_SYSTEM_UPDATE_SETTINGS);
626 if (!context.getResources().getBoolean(
627 R.bool.config_additional_system_update_setting_enable)) {
628 keys.add(KEY_UPDATE_SETTING);
633 private boolean isPropertyMissing(String property) {
634 return SystemProperties.get(property).equals("");
638 private boolean removePreferenceIfPackageNotInstalled(Preference preference) {
639 String intentUri=((PreferenceScreen) preference).getIntent().toUri(1);
640 Pattern pattern = Pattern.compile("component=([^/]+)/");
641 Matcher matcher = pattern.matcher(intentUri);
643 String packageName=matcher.find()?matcher.group(1):null;
644 if(packageName != null) {
646 PackageInfo pi = getPackageManager().getPackageInfo(packageName,
647 PackageManager.GET_ACTIVITIES);
648 if (!pi.applicationInfo.enabled) {
649 Log.e(LOG_TAG,"package "+packageName+" is disabled, hiding preference.");
650 getPreferenceScreen().removePreference(preference);
653 } catch (NameNotFoundException e) {
654 Log.e(LOG_TAG,"package "+packageName+" not installed, hiding preference.");
655 getPreferenceScreen().removePreference(preference);