Home | History | Annotate | Download | only in about
      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 
     97     public static AboutFragment newInstance() {
     98         return new AboutFragment();
     99     }
    100 
    101     @Override
    102     public void onCreate(Bundle savedInstanceState) {
    103         mUm = UserManager.get(getActivity());
    104 
    105         super.onCreate(savedInstanceState);
    106     }
    107 
    108     @Override
    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 
    200     private void removePreference(@Nullable Preference preference) {
    201         if (preference != null) {
    202             getPreferenceScreen().removePreference(preference);
    203         }
    204     }
    205 
    206     @Override
    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
    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
    225     public void onStop() {
    226         super.onStop();
    227         LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mDeviceNameReceiver);
    228     }
    229 
    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
    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
    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      */
    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 
    376     private String getSystemPropertySummary(String property) {
    377         return SystemProperties.get(property,
    378                 getResources().getString(R.string.device_info_default));
    379     }
    380 
    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 
    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
    404     public int getMetricsCategory() {
    405         return MetricsEvent.DEVICEINFO;
    406     }
    407 }
    408