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 newInstance()89 public static AboutFragment newInstance() { 90 return new AboutFragment(); 91 } 92 93 @Override onCreate(Bundle savedInstanceState)94 public void onCreate(Bundle savedInstanceState) { 95 mUm = UserManager.get(getActivity()); 96 97 super.onCreate(savedInstanceState); 98 } 99 100 @Override onCreatePreferences(Bundle savedInstanceState, String rootKey)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 removePreference(@ullable Preference preference)191 private void removePreference(@Nullable Preference preference) { 192 if (preference != null) { 193 getPreferenceScreen().removePreference(preference); 194 } 195 } 196 197 @Override onStart()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 onResume()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 onStop()217 public void onStop() { 218 super.onStop(); 219 LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mDeviceNameReceiver); 220 } 221 refreshDeviceName()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 onPreferenceLongClick(Preference preference)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 onPreferenceTreeClick(Preference preference)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 */ ciActionOnSysUpdate(PersistableBundle b)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 getSystemPropertySummary(String property)348 private String getSystemPropertySummary(String property) { 349 return SystemProperties.get(property, 350 getResources().getString(R.string.device_info_default)); 351 } 352 isWifiOnly(Context context)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 sendFeedback()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