• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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.settings;
18 
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.os.Build;
23 import android.os.Bundle;
24 import android.os.PersistableBundle;
25 import android.os.SELinux;
26 import android.os.SystemClock;
27 import android.os.SystemProperties;
28 import android.os.UserHandle;
29 import android.os.UserManager;
30 import android.provider.SearchIndexableResource;
31 import android.provider.Settings;
32 import android.support.v7.preference.Preference;
33 import android.support.v7.preference.PreferenceGroup;
34 import android.telephony.CarrierConfigManager;
35 import android.text.TextUtils;
36 import android.util.Log;
37 import android.widget.Toast;
38 
39 import com.android.internal.logging.MetricsProto.MetricsEvent;
40 import com.android.settings.dashboard.SummaryLoader;
41 import com.android.settings.search.BaseSearchIndexProvider;
42 import com.android.settings.search.Index;
43 import com.android.settings.search.Indexable;
44 import com.android.settingslib.DeviceInfoUtils;
45 import com.android.settingslib.RestrictedLockUtils;
46 
47 import java.util.ArrayList;
48 import java.util.Arrays;
49 import java.util.List;
50 
51 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
52 
53 public class DeviceInfoSettings extends SettingsPreferenceFragment implements Indexable {
54 
55     private static final String LOG_TAG = "DeviceInfoSettings";
56 
57     private static final String KEY_MANUAL = "manual";
58     private static final String KEY_REGULATORY_INFO = "regulatory_info";
59     private static final String KEY_SYSTEM_UPDATE_SETTINGS = "system_update_settings";
60     private static final String PROPERTY_URL_SAFETYLEGAL = "ro.url.safetylegal";
61     private static final String PROPERTY_SELINUX_STATUS = "ro.build.selinux";
62     private static final String KEY_KERNEL_VERSION = "kernel_version";
63     private static final String KEY_BUILD_NUMBER = "build_number";
64     private static final String KEY_DEVICE_MODEL = "device_model";
65     private static final String KEY_SELINUX_STATUS = "selinux_status";
66     private static final String KEY_BASEBAND_VERSION = "baseband_version";
67     private static final String KEY_FIRMWARE_VERSION = "firmware_version";
68     private static final String KEY_SECURITY_PATCH = "security_patch";
69     private static final String KEY_UPDATE_SETTING = "additional_system_update_settings";
70     private static final String KEY_EQUIPMENT_ID = "fcc_equipment_id";
71     private static final String PROPERTY_EQUIPMENT_ID = "ro.ril.fccid";
72     private static final String KEY_DEVICE_FEEDBACK = "device_feedback";
73     private static final String KEY_SAFETY_LEGAL = "safetylegal";
74 
75     static final int TAPS_TO_BE_A_DEVELOPER = 7;
76 
77     long[] mHits = new long[3];
78     int mDevHitCountdown;
79     Toast mDevHitToast;
80 
81     private UserManager mUm;
82 
83     private EnforcedAdmin mFunDisallowedAdmin;
84     private boolean mFunDisallowedBySystem;
85     private EnforcedAdmin mDebuggingFeaturesDisallowedAdmin;
86     private boolean mDebuggingFeaturesDisallowedBySystem;
87 
88     @Override
getMetricsCategory()89     protected int getMetricsCategory() {
90         return MetricsEvent.DEVICEINFO;
91     }
92 
93     @Override
getHelpResource()94     protected int getHelpResource() {
95         return R.string.help_uri_about;
96     }
97 
98     @Override
onCreate(Bundle icicle)99     public void onCreate(Bundle icicle) {
100         super.onCreate(icicle);
101         mUm = UserManager.get(getActivity());
102 
103         addPreferencesFromResource(R.xml.device_info_settings);
104 
105         setStringSummary(KEY_FIRMWARE_VERSION, Build.VERSION.RELEASE);
106         findPreference(KEY_FIRMWARE_VERSION).setEnabled(true);
107 
108         final String patch = DeviceInfoUtils.getSecurityPatch();
109         if (!TextUtils.isEmpty(patch)) {
110             setStringSummary(KEY_SECURITY_PATCH, patch);
111         } else {
112             getPreferenceScreen().removePreference(findPreference(KEY_SECURITY_PATCH));
113         }
114 
115         setValueSummary(KEY_BASEBAND_VERSION, "gsm.version.baseband");
116         setStringSummary(KEY_DEVICE_MODEL, Build.MODEL + DeviceInfoUtils.getMsvSuffix());
117         setValueSummary(KEY_EQUIPMENT_ID, PROPERTY_EQUIPMENT_ID);
118         setStringSummary(KEY_DEVICE_MODEL, Build.MODEL);
119         setStringSummary(KEY_BUILD_NUMBER, Build.DISPLAY);
120         findPreference(KEY_BUILD_NUMBER).setEnabled(true);
121         findPreference(KEY_KERNEL_VERSION).setSummary(DeviceInfoUtils.getFormattedKernelVersion());
122 
123         if (!SELinux.isSELinuxEnabled()) {
124             String status = getResources().getString(R.string.selinux_status_disabled);
125             setStringSummary(KEY_SELINUX_STATUS, status);
126         } else if (!SELinux.isSELinuxEnforced()) {
127             String status = getResources().getString(R.string.selinux_status_permissive);
128             setStringSummary(KEY_SELINUX_STATUS, status);
129         }
130 
131         // Remove selinux information if property is not present
132         removePreferenceIfPropertyMissing(getPreferenceScreen(), KEY_SELINUX_STATUS,
133                 PROPERTY_SELINUX_STATUS);
134 
135         // Remove Safety information preference if PROPERTY_URL_SAFETYLEGAL is not set
136         removePreferenceIfPropertyMissing(getPreferenceScreen(), KEY_SAFETY_LEGAL,
137                 PROPERTY_URL_SAFETYLEGAL);
138 
139         // Remove Equipment id preference if FCC ID is not set by RIL
140         removePreferenceIfPropertyMissing(getPreferenceScreen(), KEY_EQUIPMENT_ID,
141                 PROPERTY_EQUIPMENT_ID);
142 
143         // Remove Baseband version if wifi-only device
144         if (Utils.isWifiOnly(getActivity())) {
145             getPreferenceScreen().removePreference(findPreference(KEY_BASEBAND_VERSION));
146         }
147 
148         // Dont show feedback option if there is no reporter.
149         if (TextUtils.isEmpty(DeviceInfoUtils.getFeedbackReporterPackage(getActivity()))) {
150             getPreferenceScreen().removePreference(findPreference(KEY_DEVICE_FEEDBACK));
151         }
152 
153         /*
154          * Settings is a generic app and should not contain any device-specific
155          * info.
156          */
157         final Activity act = getActivity();
158 
159         // These are contained by the root preference screen
160         PreferenceGroup parentPreference = getPreferenceScreen();
161 
162         if (mUm.isAdminUser()) {
163             Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference,
164                     KEY_SYSTEM_UPDATE_SETTINGS,
165                     Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
166         } else {
167             // Remove for secondary users
168             removePreference(KEY_SYSTEM_UPDATE_SETTINGS);
169         }
170 
171         // Read platform settings for additional system update setting
172         removePreferenceIfBoolFalse(KEY_UPDATE_SETTING,
173                 R.bool.config_additional_system_update_setting_enable);
174 
175         // Remove manual entry if none present.
176         removePreferenceIfBoolFalse(KEY_MANUAL, R.bool.config_show_manual);
177 
178         // Remove regulatory labels if no activity present to handle intent.
179         removePreferenceIfActivityMissing(
180                 KEY_REGULATORY_INFO, Settings.ACTION_SHOW_REGULATORY_INFO);
181 
182         removePreferenceIfActivityMissing(
183                 "safety_info", "android.settings.SHOW_SAFETY_AND_REGULATORY_INFO");
184     }
185 
186     @Override
onResume()187     public void onResume() {
188         super.onResume();
189         mDevHitCountdown = getActivity().getSharedPreferences(DevelopmentSettings.PREF_FILE,
190                 Context.MODE_PRIVATE).getBoolean(DevelopmentSettings.PREF_SHOW,
191                         android.os.Build.TYPE.equals("eng")) ? -1 : TAPS_TO_BE_A_DEVELOPER;
192         mDevHitToast = null;
193         mFunDisallowedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(
194                 getActivity(), UserManager.DISALLOW_FUN, UserHandle.myUserId());
195         mFunDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(
196                 getActivity(), UserManager.DISALLOW_FUN, UserHandle.myUserId());
197         mDebuggingFeaturesDisallowedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(
198                 getActivity(), UserManager.DISALLOW_DEBUGGING_FEATURES, UserHandle.myUserId());
199         mDebuggingFeaturesDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(
200                 getActivity(), UserManager.DISALLOW_DEBUGGING_FEATURES, UserHandle.myUserId());
201     }
202 
203     @Override
onPreferenceTreeClick(Preference preference)204     public boolean onPreferenceTreeClick(Preference preference) {
205         if (preference.getKey().equals(KEY_FIRMWARE_VERSION)) {
206             System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);
207             mHits[mHits.length-1] = SystemClock.uptimeMillis();
208             if (mHits[0] >= (SystemClock.uptimeMillis()-500)) {
209                 if (mUm.hasUserRestriction(UserManager.DISALLOW_FUN)) {
210                     if (mFunDisallowedAdmin != null && !mFunDisallowedBySystem) {
211                         RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(),
212                                 mFunDisallowedAdmin);
213                     }
214                     Log.d(LOG_TAG, "Sorry, no fun for you!");
215                     return false;
216                 }
217 
218                 Intent intent = new Intent(Intent.ACTION_MAIN);
219                 intent.setClassName("android",
220                         com.android.internal.app.PlatLogoActivity.class.getName());
221                 try {
222                     startActivity(intent);
223                 } catch (Exception e) {
224                     Log.e(LOG_TAG, "Unable to start activity " + intent.toString());
225                 }
226             }
227         } else if (preference.getKey().equals(KEY_BUILD_NUMBER)) {
228             // Don't enable developer options for secondary users.
229             if (!mUm.isAdminUser()) return true;
230 
231             // Don't enable developer options until device has been provisioned
232             if (!Utils.isDeviceProvisioned(getActivity())) {
233                 return true;
234             }
235 
236             if (mUm.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES)) {
237                 if (mDebuggingFeaturesDisallowedAdmin != null &&
238                         !mDebuggingFeaturesDisallowedBySystem) {
239                     RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(),
240                             mDebuggingFeaturesDisallowedAdmin);
241                 }
242                 return true;
243             }
244 
245             if (mDevHitCountdown > 0) {
246                 mDevHitCountdown--;
247                 if (mDevHitCountdown == 0) {
248                     getActivity().getSharedPreferences(DevelopmentSettings.PREF_FILE,
249                             Context.MODE_PRIVATE).edit().putBoolean(
250                                     DevelopmentSettings.PREF_SHOW, true).apply();
251                     if (mDevHitToast != null) {
252                         mDevHitToast.cancel();
253                     }
254                     mDevHitToast = Toast.makeText(getActivity(), R.string.show_dev_on,
255                             Toast.LENGTH_LONG);
256                     mDevHitToast.show();
257                     // This is good time to index the Developer Options
258                     Index.getInstance(
259                             getActivity().getApplicationContext()).updateFromClassNameResource(
260                                     DevelopmentSettings.class.getName(), true, true);
261 
262                 } else if (mDevHitCountdown > 0
263                         && mDevHitCountdown < (TAPS_TO_BE_A_DEVELOPER-2)) {
264                     if (mDevHitToast != null) {
265                         mDevHitToast.cancel();
266                     }
267                     mDevHitToast = Toast.makeText(getActivity(), getResources().getQuantityString(
268                             R.plurals.show_dev_countdown, mDevHitCountdown, mDevHitCountdown),
269                             Toast.LENGTH_SHORT);
270                     mDevHitToast.show();
271                 }
272             } else if (mDevHitCountdown < 0) {
273                 if (mDevHitToast != null) {
274                     mDevHitToast.cancel();
275                 }
276                 mDevHitToast = Toast.makeText(getActivity(), R.string.show_dev_already,
277                         Toast.LENGTH_LONG);
278                 mDevHitToast.show();
279             }
280         } else if (preference.getKey().equals(KEY_DEVICE_FEEDBACK)) {
281             sendFeedback();
282         } else if(preference.getKey().equals(KEY_SYSTEM_UPDATE_SETTINGS)) {
283             CarrierConfigManager configManager =
284                     (CarrierConfigManager) getSystemService(Context.CARRIER_CONFIG_SERVICE);
285             PersistableBundle b = configManager.getConfig();
286             if (b != null && b.getBoolean(CarrierConfigManager.KEY_CI_ACTION_ON_SYS_UPDATE_BOOL)) {
287                 ciActionOnSysUpdate(b);
288             }
289         }
290         return super.onPreferenceTreeClick(preference);
291     }
292 
293     /**
294      * Trigger client initiated action (send intent) on system update
295      */
ciActionOnSysUpdate(PersistableBundle b)296     private void ciActionOnSysUpdate(PersistableBundle b) {
297         String intentStr = b.getString(CarrierConfigManager.
298                 KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING);
299         if (!TextUtils.isEmpty(intentStr)) {
300             String extra = b.getString(CarrierConfigManager.
301                     KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING);
302             String extraVal = b.getString(CarrierConfigManager.
303                     KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING);
304 
305             Intent intent = new Intent(intentStr);
306             if (!TextUtils.isEmpty(extra)) {
307                 intent.putExtra(extra, extraVal);
308             }
309             Log.d(LOG_TAG, "ciActionOnSysUpdate: broadcasting intent " + intentStr +
310                     " with extra " + extra + ", " + extraVal);
311             getActivity().getApplicationContext().sendBroadcast(intent);
312         }
313     }
314 
removePreferenceIfPropertyMissing(PreferenceGroup preferenceGroup, String preference, String property )315     private void removePreferenceIfPropertyMissing(PreferenceGroup preferenceGroup,
316             String preference, String property ) {
317         if (SystemProperties.get(property).equals("")) {
318             // Property is missing so remove preference from group
319             try {
320                 preferenceGroup.removePreference(findPreference(preference));
321             } catch (RuntimeException e) {
322                 Log.d(LOG_TAG, "Property '" + property + "' missing and no '"
323                         + preference + "' preference");
324             }
325         }
326     }
327 
removePreferenceIfActivityMissing(String preferenceKey, String action)328     private void removePreferenceIfActivityMissing(String preferenceKey, String action) {
329         final Intent intent = new Intent(action);
330         if (getPackageManager().queryIntentActivities(intent, 0).isEmpty()) {
331             Preference pref = findPreference(preferenceKey);
332             if (pref != null) {
333                 getPreferenceScreen().removePreference(pref);
334             }
335         }
336     }
337 
removePreferenceIfBoolFalse(String preference, int resId)338     private void removePreferenceIfBoolFalse(String preference, int resId) {
339         if (!getResources().getBoolean(resId)) {
340             Preference pref = findPreference(preference);
341             if (pref != null) {
342                 getPreferenceScreen().removePreference(pref);
343             }
344         }
345     }
346 
setStringSummary(String preference, String value)347     private void setStringSummary(String preference, String value) {
348         try {
349             findPreference(preference).setSummary(value);
350         } catch (RuntimeException e) {
351             findPreference(preference).setSummary(
352                 getResources().getString(R.string.device_info_default));
353         }
354     }
355 
setValueSummary(String preference, String property)356     private void setValueSummary(String preference, String property) {
357         try {
358             findPreference(preference).setSummary(
359                     SystemProperties.get(property,
360                             getResources().getString(R.string.device_info_default)));
361         } catch (RuntimeException e) {
362             // No recovery
363         }
364     }
365 
sendFeedback()366     private void sendFeedback() {
367         String reporterPackage = DeviceInfoUtils.getFeedbackReporterPackage(getActivity());
368         if (TextUtils.isEmpty(reporterPackage)) {
369             return;
370         }
371         Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
372         intent.setPackage(reporterPackage);
373         startActivityForResult(intent, 0);
374     }
375 
376     private static class SummaryProvider implements SummaryLoader.SummaryProvider {
377 
378         private final Context mContext;
379         private final SummaryLoader mSummaryLoader;
380 
SummaryProvider(Context context, SummaryLoader summaryLoader)381         public SummaryProvider(Context context, SummaryLoader summaryLoader) {
382             mContext = context;
383             mSummaryLoader = summaryLoader;
384         }
385 
386         @Override
setListening(boolean listening)387         public void setListening(boolean listening) {
388             if (listening) {
389                 mSummaryLoader.setSummary(this, mContext.getString(R.string.about_summary,
390                         Build.VERSION.RELEASE));
391             }
392         }
393     }
394 
395     public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
396             = new SummaryLoader.SummaryProviderFactory() {
397         @Override
398         public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
399                                                                    SummaryLoader summaryLoader) {
400             return new SummaryProvider(activity, summaryLoader);
401         }
402     };
403 
404     /**
405      * For Search.
406      */
407     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
408         new BaseSearchIndexProvider() {
409 
410             @Override
411             public List<SearchIndexableResource> getXmlResourcesToIndex(
412                     Context context, boolean enabled) {
413                 final SearchIndexableResource sir = new SearchIndexableResource(context);
414                 sir.xmlResId = R.xml.device_info_settings;
415                 return Arrays.asList(sir);
416             }
417 
418             @Override
419             public List<String> getNonIndexableKeys(Context context) {
420                 final List<String> keys = new ArrayList<String>();
421                 if (isPropertyMissing(PROPERTY_SELINUX_STATUS)) {
422                     keys.add(KEY_SELINUX_STATUS);
423                 }
424                 if (isPropertyMissing(PROPERTY_URL_SAFETYLEGAL)) {
425                     keys.add(KEY_SAFETY_LEGAL);
426                 }
427                 if (isPropertyMissing(PROPERTY_EQUIPMENT_ID)) {
428                     keys.add(KEY_EQUIPMENT_ID);
429                 }
430                 // Remove Baseband version if wifi-only device
431                 if (Utils.isWifiOnly(context)) {
432                     keys.add((KEY_BASEBAND_VERSION));
433                 }
434                 // Dont show feedback option if there is no reporter.
435                 if (TextUtils.isEmpty(DeviceInfoUtils.getFeedbackReporterPackage(context))) {
436                     keys.add(KEY_DEVICE_FEEDBACK);
437                 }
438                 final UserManager um = UserManager.get(context);
439                 // TODO: system update needs to be fixed for non-owner user b/22760654
440                 if (!um.isAdminUser()) {
441                     keys.add(KEY_SYSTEM_UPDATE_SETTINGS);
442                 }
443                 if (!context.getResources().getBoolean(
444                         R.bool.config_additional_system_update_setting_enable)) {
445                     keys.add(KEY_UPDATE_SETTING);
446                 }
447                 return keys;
448             }
449 
450             private boolean isPropertyMissing(String property) {
451                 return SystemProperties.get(property).equals("");
452             }
453         };
454 
455 }
456