• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.tv.settings.about;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.content.pm.ResolveInfo;
24 import android.os.Build;
25 import android.os.Bundle;
26 import android.os.PersistableBundle;
27 import android.os.SELinux;
28 import android.os.SystemClock;
29 import android.os.SystemProperties;
30 import android.os.UserManager;
31 import android.support.annotation.Nullable;
32 import android.support.v17.preference.LeanbackSettingsFragment;
33 import android.support.v4.content.LocalBroadcastManager;
34 import android.support.v7.preference.Preference;
35 import android.support.v7.preference.PreferenceScreen;
36 import android.telephony.CarrierConfigManager;
37 import android.text.TextUtils;
38 import android.util.Log;
39 import android.util.Pair;
40 import android.widget.Toast;
41 
42 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
43 import com.android.internal.telephony.TelephonyProperties;
44 import com.android.settingslib.DeviceInfoUtils;
45 import com.android.settingslib.Utils;
46 import com.android.settingslib.development.DevelopmentSettingsEnabler;
47 import com.android.tv.settings.LongClickPreference;
48 import com.android.tv.settings.MainFragment;
49 import com.android.tv.settings.PreferenceUtils;
50 import com.android.tv.settings.R;
51 import com.android.tv.settings.SettingsPreferenceFragment;
52 import com.android.tv.settings.name.DeviceManager;
53 
54 /**
55  * The "About" screen in TV settings.
56  */
57 public class AboutFragment extends SettingsPreferenceFragment implements
58         LongClickPreference.OnLongClickListener {
59     private static final String TAG = "AboutFragment";
60 
61     private static final String KEY_MANUAL = "manual";
62     private static final String KEY_REGULATORY_INFO = "regulatory_info";
63     private static final String KEY_SYSTEM_UPDATE_SETTINGS = "system_update_settings";
64     private static final String PROPERTY_URL_SAFETYLEGAL = "ro.url.safetylegal";
65     private static final String PROPERTY_SELINUX_STATUS = "ro.build.selinux";
66     private static final String KEY_KERNEL_VERSION = "kernel_version";
67     private static final String KEY_BUILD_NUMBER = "build_number";
68     private static final String KEY_DEVICE_MODEL = "device_model";
69     private static final String KEY_SELINUX_STATUS = "selinux_status";
70     private static final String KEY_BASEBAND_VERSION = "baseband_version";
71     private static final String KEY_FIRMWARE_VERSION = "firmware_version";
72     private static final String KEY_SECURITY_PATCH = "security_patch";
73     private static final String KEY_UPDATE_SETTING = "additional_system_update_settings";
74     private static final String KEY_EQUIPMENT_ID = "fcc_equipment_id";
75     private static final String PROPERTY_EQUIPMENT_ID = "ro.ril.fccid";
76     private static final String KEY_DEVICE_FEEDBACK = "device_feedback";
77     private static final String KEY_SAFETY_LEGAL = "safetylegal";
78     private static final String KEY_DEVICE_NAME = "device_name";
79     private static final String KEY_RESTART = "restart";
80     private static final String KEY_TUTORIALS = "tutorials";
81 
82     static final int TAPS_TO_BE_A_DEVELOPER = 7;
83 
84     long[] mHits = new long[3];
85     int mDevHitCountdown;
86     Toast mDevHitToast;
87 
88     private UserManager mUm;
89 
90     private final BroadcastReceiver mDeviceNameReceiver = new BroadcastReceiver() {
91         @Override
92         public void onReceive(Context context, Intent intent) {
93             refreshDeviceName();
94         }
95     };
96 
newInstance()97     public static AboutFragment newInstance() {
98         return new AboutFragment();
99     }
100 
101     @Override
onCreate(Bundle savedInstanceState)102     public void onCreate(Bundle savedInstanceState) {
103         mUm = UserManager.get(getActivity());
104 
105         super.onCreate(savedInstanceState);
106     }
107 
108     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)109     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
110         setPreferencesFromResource(R.xml.device_info_settings, null);
111         final PreferenceScreen screen = getPreferenceScreen();
112 
113         refreshDeviceName();
114         final Preference deviceNamePref = findPreference(KEY_DEVICE_NAME);
115         PreferenceUtils.resolveSystemActivityOrRemove(getActivity(), screen, deviceNamePref, 0);
116 
117         final Preference firmwareVersionPref = findPreference(KEY_FIRMWARE_VERSION);
118         firmwareVersionPref.setSummary(Build.VERSION.RELEASE);
119         firmwareVersionPref.setEnabled(true);
120 
121         final Preference securityPatchPref = findPreference(KEY_SECURITY_PATCH);
122         final String patch = DeviceInfoUtils.getSecurityPatch();
123         if (!TextUtils.isEmpty(patch)) {
124             securityPatchPref.setSummary(patch);
125         } else {
126             removePreference(securityPatchPref);
127         }
128 
129         final LongClickPreference restartPref = (LongClickPreference) findPreference(KEY_RESTART);
130         restartPref.setLongClickListener(this);
131 
132         findPreference(KEY_BASEBAND_VERSION).setSummary(
133                 getSystemPropertySummary(TelephonyProperties.PROPERTY_BASEBAND_VERSION));
134         findPreference(KEY_DEVICE_MODEL).setSummary(Build.MODEL + DeviceInfoUtils.getMsvSuffix());
135         findPreference(KEY_EQUIPMENT_ID)
136                 .setSummary(getSystemPropertySummary(PROPERTY_EQUIPMENT_ID));
137 
138         final Preference buildNumberPref = findPreference(KEY_BUILD_NUMBER);
139         buildNumberPref.setSummary(Build.DISPLAY);
140         buildNumberPref.setEnabled(true);
141         findPreference(KEY_KERNEL_VERSION)
142                 .setSummary(DeviceInfoUtils.getFormattedKernelVersion(getContext()));
143 
144         final Preference selinuxPref = findPreference(KEY_SELINUX_STATUS);
145         if (!SELinux.isSELinuxEnabled()) {
146             selinuxPref.setSummary(R.string.selinux_status_disabled);
147         } else if (!SELinux.isSELinuxEnforced()) {
148             selinuxPref.setSummary(R.string.selinux_status_permissive);
149         }
150 
151         // Remove selinux information if property is not present
152         if (TextUtils.isEmpty(SystemProperties.get(PROPERTY_SELINUX_STATUS))) {
153             removePreference(selinuxPref);
154         }
155 
156         // Remove Safety information preference if PROPERTY_URL_SAFETYLEGAL is not set
157         if (TextUtils.isEmpty(SystemProperties.get(PROPERTY_URL_SAFETYLEGAL))) {
158             removePreference(findPreference(KEY_SAFETY_LEGAL));
159         }
160 
161         // Remove Equipment id preference if FCC ID is not set by RIL
162         if (TextUtils.isEmpty(SystemProperties.get(PROPERTY_EQUIPMENT_ID))) {
163             removePreference(findPreference(KEY_EQUIPMENT_ID));
164         }
165 
166         // Remove Baseband version if wifi-only device
167         if (Utils.isWifiOnly(getActivity())) {
168             removePreference(findPreference(KEY_BASEBAND_VERSION));
169         }
170 
171         // Dont show feedback option if there is no reporter.
172         if (TextUtils.isEmpty(DeviceInfoUtils.getFeedbackReporterPackage(getActivity()))) {
173             removePreference(findPreference(KEY_DEVICE_FEEDBACK));
174         }
175 
176         final Preference updateSettingsPref = findPreference(KEY_SYSTEM_UPDATE_SETTINGS);
177         if (mUm.isAdminUser()) {
178             PreferenceUtils.resolveSystemActivityOrRemove(getActivity(), screen,
179                     updateSettingsPref, PreferenceUtils.FLAG_SET_TITLE);
180         } else if (updateSettingsPref != null) {
181             // Remove for secondary users
182             removePreference(updateSettingsPref);
183         }
184 
185         // Read platform settings for additional system update setting
186         if (!getResources().getBoolean(R.bool.config_additional_system_update_setting_enable)) {
187             removePreference(findPreference(KEY_UPDATE_SETTING));
188         }
189 
190         // Remove manual entry if none present.
191         if (!getResources().getBoolean(R.bool.config_show_manual)) {
192             removePreference(findPreference(KEY_MANUAL));
193         }
194 
195         // Remove regulatory information if none present.
196         final Preference regulatoryPref = findPreference(KEY_REGULATORY_INFO);
197         PreferenceUtils.resolveSystemActivityOrRemove(getActivity(), screen, regulatoryPref, 0);
198     }
199 
removePreference(@ullable Preference preference)200     private void removePreference(@Nullable Preference preference) {
201         if (preference != null) {
202             getPreferenceScreen().removePreference(preference);
203         }
204     }
205 
206     @Override
onStart()207     public void onStart() {
208         super.onStart();
209         refreshDeviceName();
210 
211         LocalBroadcastManager.getInstance(getContext()).registerReceiver(mDeviceNameReceiver,
212                 new IntentFilter(DeviceManager.ACTION_DEVICE_NAME_UPDATE));
213     }
214 
215     @Override
onResume()216     public void onResume() {
217         super.onResume();
218         mDevHitCountdown = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(getContext())
219                 ? -1 : TAPS_TO_BE_A_DEVELOPER;
220         mDevHitToast = null;
221         updateTutorials();
222     }
223 
224     @Override
onStop()225     public void onStop() {
226         super.onStop();
227         LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mDeviceNameReceiver);
228     }
229 
refreshDeviceName()230     private void refreshDeviceName() {
231         final Preference deviceNamePref = findPreference(KEY_DEVICE_NAME);
232         if (deviceNamePref != null) {
233             deviceNamePref.setSummary(DeviceManager.getDeviceName(getActivity()));
234         }
235     }
236 
237     @Override
onPreferenceLongClick(Preference preference)238     public boolean onPreferenceLongClick(Preference preference) {
239         if (TextUtils.equals(preference.getKey(), KEY_RESTART)) {
240             if (getCallbackFragment() instanceof LeanbackSettingsFragment) {
241                 LeanbackSettingsFragment callback =
242                         (LeanbackSettingsFragment) getCallbackFragment();
243                 callback.startImmersiveFragment(
244                         RebootConfirmFragment.newInstance(true /* safeMode */));
245                 return true;
246             }
247         }
248         return false;
249     }
250 
251     @Override
onPreferenceTreeClick(Preference preference)252     public boolean onPreferenceTreeClick(Preference preference) {
253         switch (preference.getKey()) {
254             case KEY_FIRMWARE_VERSION:
255                 System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1);
256                 mHits[mHits.length - 1] = SystemClock.uptimeMillis();
257                 if (mHits[0] >= (SystemClock.uptimeMillis() - 500)) {
258                     if (mUm.hasUserRestriction(UserManager.DISALLOW_FUN)) {
259                         Log.d(TAG, "Sorry, no fun for you!");
260                         return false;
261                     }
262 
263                     Intent intent = new Intent(Intent.ACTION_MAIN);
264                     intent.setClassName("android",
265                             com.android.internal.app.PlatLogoActivity.class.getName());
266                     try {
267                         startActivity(intent);
268                     } catch (Exception e) {
269                         Log.e(TAG, "Unable to start activity " + intent.toString());
270                     }
271                 }
272                 break;
273             case KEY_BUILD_NUMBER:
274                 // Don't enable developer options for secondary users.
275                 if (!mUm.isAdminUser()) {
276                     mMetricsFeatureProvider.action(getContext(),
277                             MetricsEvent.ACTION_SETTINGS_BUILD_NUMBER_PREF);
278                     return true;
279                 }
280 
281                 if (mUm.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES)) {
282                     mMetricsFeatureProvider.action(getContext(),
283                             MetricsEvent.ACTION_SETTINGS_BUILD_NUMBER_PREF);
284                     return true;
285                 }
286 
287                 if (mDevHitCountdown > 0) {
288                     mDevHitCountdown--;
289                     if (mDevHitCountdown == 0) {
290                         DevelopmentSettingsEnabler
291                                 .setDevelopmentSettingsEnabled(getContext(), true);
292                         if (mDevHitToast != null) {
293                             mDevHitToast.cancel();
294                         }
295                         mDevHitToast = Toast.makeText(getActivity(), R.string.show_dev_on,
296                                 Toast.LENGTH_LONG);
297                         mDevHitToast.show();
298                         // This is good time to index the Developer Options
299 //                    Index.getInstance(
300 //                            getActivity().getApplicationContext()).updateFromClassNameResource(
301 //                            DevelopmentSettings.class.getName(), true, true);
302                         mMetricsFeatureProvider.action(
303                                 getContext(), MetricsEvent.ACTION_SETTINGS_BUILD_NUMBER_PREF,
304                                 Pair.create(MetricsEvent
305                                         .FIELD_SETTINGS_BUILD_NUMBER_DEVELOPER_MODE_ENABLED,
306                                 0));
307                     } else if (mDevHitCountdown > 0
308                             && mDevHitCountdown < (TAPS_TO_BE_A_DEVELOPER - 2)) {
309                         if (mDevHitToast != null) {
310                             mDevHitToast.cancel();
311                         }
312                         mDevHitToast = Toast
313                                 .makeText(getActivity(), getResources().getQuantityString(
314                                         R.plurals.show_dev_countdown, mDevHitCountdown,
315                                         mDevHitCountdown),
316                                         Toast.LENGTH_SHORT);
317                         mDevHitToast.show();
318                     }
319                     mMetricsFeatureProvider.action(
320                             getContext(), MetricsEvent.ACTION_SETTINGS_BUILD_NUMBER_PREF,
321                             Pair.create(
322                                     MetricsEvent.FIELD_SETTINGS_BUILD_NUMBER_DEVELOPER_MODE_ENABLED,
323                             0));
324                 } else if (mDevHitCountdown < 0) {
325                     if (mDevHitToast != null) {
326                         mDevHitToast.cancel();
327                     }
328                     mDevHitToast = Toast.makeText(getActivity(), R.string.show_dev_already,
329                             Toast.LENGTH_LONG);
330                     mDevHitToast.show();
331                     mMetricsFeatureProvider.action(
332                             getContext(), MetricsEvent.ACTION_SETTINGS_BUILD_NUMBER_PREF,
333                             Pair.create(
334                                     MetricsEvent.FIELD_SETTINGS_BUILD_NUMBER_DEVELOPER_MODE_ENABLED,
335                             1));
336                 }
337                 break;
338             case KEY_DEVICE_FEEDBACK:
339                 sendFeedback();
340                 break;
341             case KEY_SYSTEM_UPDATE_SETTINGS:
342                 CarrierConfigManager configManager = (CarrierConfigManager)
343                         getActivity().getSystemService(Context.CARRIER_CONFIG_SERVICE);
344                 PersistableBundle b = configManager.getConfig();
345                 if (b != null &&
346                         b.getBoolean(CarrierConfigManager.KEY_CI_ACTION_ON_SYS_UPDATE_BOOL)) {
347                     ciActionOnSysUpdate(b);
348                 }
349                 break;
350         }
351         return super.onPreferenceTreeClick(preference);
352     }
353 
354     /**
355      * Trigger client initiated action (send intent) on system update
356      */
ciActionOnSysUpdate(PersistableBundle b)357     private void ciActionOnSysUpdate(PersistableBundle b) {
358         String intentStr = b.getString(CarrierConfigManager.
359                 KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING);
360         if (!TextUtils.isEmpty(intentStr)) {
361             String extra = b.getString(CarrierConfigManager.
362                     KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING);
363             String extraVal = b.getString(CarrierConfigManager.
364                     KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING);
365 
366             Intent intent = new Intent(intentStr);
367             if (!TextUtils.isEmpty(extra)) {
368                 intent.putExtra(extra, extraVal);
369             }
370             Log.d(TAG, "ciActionOnSysUpdate: broadcasting intent " + intentStr +
371                     " with extra " + extra + ", " + extraVal);
372             getActivity().getApplicationContext().sendBroadcast(intent);
373         }
374     }
375 
getSystemPropertySummary(String property)376     private String getSystemPropertySummary(String property) {
377         return SystemProperties.get(property,
378                 getResources().getString(R.string.device_info_default));
379     }
380 
sendFeedback()381     private void sendFeedback() {
382         String reporterPackage = DeviceInfoUtils.getFeedbackReporterPackage(getActivity());
383         if (TextUtils.isEmpty(reporterPackage)) {
384             return;
385         }
386         Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
387         intent.setPackage(reporterPackage);
388         startActivityForResult(intent, 0);
389     }
390 
updateTutorials()391     private void updateTutorials() {
392         final Preference deviceTutorialsPref = findPreference(KEY_TUTORIALS);
393         if (deviceTutorialsPref != null) {
394             final ResolveInfo info = MainFragment.systemIntentIsHandled(getContext(),
395                     deviceTutorialsPref.getIntent());
396             deviceTutorialsPref.setVisible(info != null);
397             if (info != null) {
398                 deviceTutorialsPref.setTitle(info.loadLabel(getContext().getPackageManager()));
399             }
400         }
401     }
402 
403     @Override
getMetricsCategory()404     public int getMetricsCategory() {
405         return MetricsEvent.DEVICEINFO;
406     }
407 }
408