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