• 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 static android.Manifest.permission.READ_EXTERNAL_STORAGE;
20 
21 import android.app.ActionBar;
22 import android.app.Activity;
23 import android.app.ActivityManagerNative;
24 import android.app.ActivityThread;
25 import android.app.AlertDialog;
26 import android.app.Dialog;
27 import android.app.DialogFragment;
28 import android.app.admin.DevicePolicyManager;
29 import android.app.backup.IBackupManager;
30 import android.content.ContentResolver;
31 import android.content.Context;
32 import android.content.DialogInterface;
33 import android.content.DialogInterface.OnClickListener;
34 import android.content.Intent;
35 import android.content.pm.ApplicationInfo;
36 import android.content.pm.PackageManager;
37 import android.os.AsyncTask;
38 import android.os.BatteryManager;
39 import android.os.Build;
40 import android.os.Bundle;
41 import android.os.IBinder;
42 import android.os.Parcel;
43 import android.os.RemoteException;
44 import android.os.ServiceManager;
45 import android.os.StrictMode;
46 import android.os.SystemProperties;
47 import android.os.Trace;
48 import android.preference.CheckBoxPreference;
49 import android.preference.ListPreference;
50 import android.preference.MultiCheckPreference;
51 import android.preference.Preference;
52 import android.preference.Preference.OnPreferenceChangeListener;
53 import android.preference.PreferenceFragment;
54 import android.preference.PreferenceScreen;
55 import android.provider.Settings;
56 import android.text.TextUtils;
57 import android.view.Gravity;
58 import android.view.HardwareRenderer;
59 import android.view.IWindowManager;
60 import android.view.View;
61 import android.widget.CompoundButton;
62 import android.widget.Switch;
63 
64 import java.util.ArrayList;
65 import java.util.HashSet;
66 
67 /*
68  * Displays preferences for application developers.
69  */
70 public class DevelopmentSettings extends PreferenceFragment
71         implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
72                 OnPreferenceChangeListener, CompoundButton.OnCheckedChangeListener {
73 
74     private static final String ENABLE_ADB = "enable_adb";
75     private static final String KEEP_SCREEN_ON = "keep_screen_on";
76     private static final String ALLOW_MOCK_LOCATION = "allow_mock_location";
77     private static final String HDCP_CHECKING_KEY = "hdcp_checking";
78     private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
79     private static final String ENFORCE_READ_EXTERNAL = "enforce_read_external";
80     private static final String LOCAL_BACKUP_PASSWORD = "local_backup_password";
81     private static final String HARDWARE_UI_PROPERTY = "persist.sys.ui.hw";
82 
83     private static final String DEBUG_APP_KEY = "debug_app";
84     private static final String WAIT_FOR_DEBUGGER_KEY = "wait_for_debugger";
85     private static final String STRICT_MODE_KEY = "strict_mode";
86     private static final String POINTER_LOCATION_KEY = "pointer_location";
87     private static final String SHOW_TOUCHES_KEY = "show_touches";
88     private static final String SHOW_SCREEN_UPDATES_KEY = "show_screen_updates";
89     private static final String DISABLE_OVERLAYS_KEY = "disable_overlays";
90     private static final String SHOW_CPU_USAGE_KEY = "show_cpu_usage";
91     private static final String FORCE_HARDWARE_UI_KEY = "force_hw_ui";
92     private static final String TRACK_FRAME_TIME_KEY = "track_frame_time";
93     private static final String SHOW_HW_SCREEN_UPDATES_KEY = "show_hw_screen_udpates";
94     private static final String DEBUG_LAYOUT_KEY = "debug_layout";
95     private static final String WINDOW_ANIMATION_SCALE_KEY = "window_animation_scale";
96     private static final String TRANSITION_ANIMATION_SCALE_KEY = "transition_animation_scale";
97     private static final String ANIMATOR_DURATION_SCALE_KEY = "animator_duration_scale";
98 
99     private static final String ENABLE_TRACES_KEY = "enable_traces";
100 
101     private static final String IMMEDIATELY_DESTROY_ACTIVITIES_KEY
102             = "immediately_destroy_activities";
103     private static final String APP_PROCESS_LIMIT_KEY = "app_process_limit";
104 
105     private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
106 
107     private static final String TAG_CONFIRM_ENFORCE = "confirm_enforce";
108 
109     private static final int RESULT_DEBUG_APP = 1000;
110 
111     private IWindowManager mWindowManager;
112     private IBackupManager mBackupManager;
113     private DevicePolicyManager mDpm;
114 
115     private Switch mEnabledSwitch;
116     private boolean mLastEnabledState;
117     private boolean mHaveDebugSettings;
118     private boolean mDontPokeProperties;
119 
120     private CheckBoxPreference mEnableAdb;
121     private CheckBoxPreference mKeepScreenOn;
122     private CheckBoxPreference mEnforceReadExternal;
123     private CheckBoxPreference mAllowMockLocation;
124     private PreferenceScreen mPassword;
125 
126     private String mDebugApp;
127     private Preference mDebugAppPref;
128     private CheckBoxPreference mWaitForDebugger;
129 
130     private CheckBoxPreference mStrictMode;
131     private CheckBoxPreference mPointerLocation;
132     private CheckBoxPreference mShowTouches;
133     private CheckBoxPreference mShowScreenUpdates;
134     private CheckBoxPreference mDisableOverlays;
135     private CheckBoxPreference mShowCpuUsage;
136     private CheckBoxPreference mForceHardwareUi;
137     private CheckBoxPreference mTrackFrameTime;
138     private CheckBoxPreference mShowHwScreenUpdates;
139     private CheckBoxPreference mDebugLayout;
140     private ListPreference mWindowAnimationScale;
141     private ListPreference mTransitionAnimationScale;
142     private ListPreference mAnimatorDurationScale;
143     private MultiCheckPreference mEnableTracesPref;
144 
145     private CheckBoxPreference mImmediatelyDestroyActivities;
146     private ListPreference mAppProcessLimit;
147 
148     private CheckBoxPreference mShowAllANRs;
149 
150     private final ArrayList<Preference> mAllPrefs = new ArrayList<Preference>();
151     private final ArrayList<CheckBoxPreference> mResetCbPrefs
152             = new ArrayList<CheckBoxPreference>();
153 
154     private final HashSet<Preference> mDisabledPrefs = new HashSet<Preference>();
155 
156     // To track whether a confirmation dialog was clicked.
157     private boolean mDialogClicked;
158     private Dialog mEnableDialog;
159     private Dialog mAdbDialog;
160 
161     @Override
onCreate(Bundle icicle)162     public void onCreate(Bundle icicle) {
163         super.onCreate(icicle);
164 
165         mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
166         mBackupManager = IBackupManager.Stub.asInterface(
167                 ServiceManager.getService(Context.BACKUP_SERVICE));
168         mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
169 
170         addPreferencesFromResource(R.xml.development_prefs);
171 
172         mEnableAdb = findAndInitCheckboxPref(ENABLE_ADB);
173         mKeepScreenOn = findAndInitCheckboxPref(KEEP_SCREEN_ON);
174         mEnforceReadExternal = findAndInitCheckboxPref(ENFORCE_READ_EXTERNAL);
175         mAllowMockLocation = findAndInitCheckboxPref(ALLOW_MOCK_LOCATION);
176         mPassword = (PreferenceScreen) findPreference(LOCAL_BACKUP_PASSWORD);
177         mAllPrefs.add(mPassword);
178 
179         mDebugAppPref = findPreference(DEBUG_APP_KEY);
180         mAllPrefs.add(mDebugAppPref);
181         mWaitForDebugger = findAndInitCheckboxPref(WAIT_FOR_DEBUGGER_KEY);
182         mStrictMode = findAndInitCheckboxPref(STRICT_MODE_KEY);
183         mPointerLocation = findAndInitCheckboxPref(POINTER_LOCATION_KEY);
184         mShowTouches = findAndInitCheckboxPref(SHOW_TOUCHES_KEY);
185         mShowScreenUpdates = findAndInitCheckboxPref(SHOW_SCREEN_UPDATES_KEY);
186         mDisableOverlays = findAndInitCheckboxPref(DISABLE_OVERLAYS_KEY);
187         mShowCpuUsage = findAndInitCheckboxPref(SHOW_CPU_USAGE_KEY);
188         mForceHardwareUi = findAndInitCheckboxPref(FORCE_HARDWARE_UI_KEY);
189         mTrackFrameTime = findAndInitCheckboxPref(TRACK_FRAME_TIME_KEY);
190         mShowHwScreenUpdates = findAndInitCheckboxPref(SHOW_HW_SCREEN_UPDATES_KEY);
191         mDebugLayout = findAndInitCheckboxPref(DEBUG_LAYOUT_KEY);
192         mWindowAnimationScale = (ListPreference) findPreference(WINDOW_ANIMATION_SCALE_KEY);
193         mAllPrefs.add(mWindowAnimationScale);
194         mWindowAnimationScale.setOnPreferenceChangeListener(this);
195         mTransitionAnimationScale = (ListPreference) findPreference(TRANSITION_ANIMATION_SCALE_KEY);
196         mAllPrefs.add(mTransitionAnimationScale);
197         mTransitionAnimationScale.setOnPreferenceChangeListener(this);
198         mAnimatorDurationScale = (ListPreference) findPreference(ANIMATOR_DURATION_SCALE_KEY);
199         mAllPrefs.add(mAnimatorDurationScale);
200         mAnimatorDurationScale.setOnPreferenceChangeListener(this);
201         mEnableTracesPref = (MultiCheckPreference)findPreference(ENABLE_TRACES_KEY);
202         String[] traceValues = new String[Trace.TRACE_TAGS.length];
203         for (int i=Trace.TRACE_FLAGS_START_BIT; i<traceValues.length; i++) {
204             traceValues[i] = Integer.toString(1<<i);
205         }
206         mEnableTracesPref.setEntries(Trace.TRACE_TAGS);
207         mEnableTracesPref.setEntryValues(traceValues);
208         mAllPrefs.add(mEnableTracesPref);
209         mEnableTracesPref.setOnPreferenceChangeListener(this);
210 
211         mImmediatelyDestroyActivities = (CheckBoxPreference) findPreference(
212                 IMMEDIATELY_DESTROY_ACTIVITIES_KEY);
213         mAllPrefs.add(mImmediatelyDestroyActivities);
214         mResetCbPrefs.add(mImmediatelyDestroyActivities);
215         mAppProcessLimit = (ListPreference) findPreference(APP_PROCESS_LIMIT_KEY);
216         mAllPrefs.add(mAppProcessLimit);
217         mAppProcessLimit.setOnPreferenceChangeListener(this);
218 
219         mShowAllANRs = (CheckBoxPreference) findPreference(
220                 SHOW_ALL_ANRS_KEY);
221         mAllPrefs.add(mShowAllANRs);
222         mResetCbPrefs.add(mShowAllANRs);
223 
224         Preference hdcpChecking = findPreference(HDCP_CHECKING_KEY);
225         if (hdcpChecking != null) {
226             mAllPrefs.add(hdcpChecking);
227         }
228         removeHdcpOptionsForProduction();
229     }
230 
findAndInitCheckboxPref(String key)231     private CheckBoxPreference findAndInitCheckboxPref(String key) {
232         CheckBoxPreference pref = (CheckBoxPreference) findPreference(key);
233         if (pref == null) {
234             throw new IllegalArgumentException("Cannot find preference with key = " + key);
235         }
236         mAllPrefs.add(pref);
237         mResetCbPrefs.add(pref);
238         return pref;
239     }
240 
241     @Override
onActivityCreated(Bundle savedInstanceState)242     public void onActivityCreated(Bundle savedInstanceState) {
243         super.onActivityCreated(savedInstanceState);
244 
245         final Activity activity = getActivity();
246         mEnabledSwitch = new Switch(activity);
247 
248         final int padding = activity.getResources().getDimensionPixelSize(
249                 R.dimen.action_bar_switch_padding);
250         mEnabledSwitch.setPadding(0, 0, padding, 0);
251         mEnabledSwitch.setOnCheckedChangeListener(this);
252     }
253 
254     @Override
onStart()255     public void onStart() {
256         super.onStart();
257         final Activity activity = getActivity();
258         activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
259                 ActionBar.DISPLAY_SHOW_CUSTOM);
260         activity.getActionBar().setCustomView(mEnabledSwitch, new ActionBar.LayoutParams(
261                 ActionBar.LayoutParams.WRAP_CONTENT,
262                 ActionBar.LayoutParams.WRAP_CONTENT,
263                 Gravity.CENTER_VERTICAL | Gravity.RIGHT));
264     }
265 
266     @Override
onStop()267     public void onStop() {
268         super.onStop();
269         final Activity activity = getActivity();
270         activity.getActionBar().setDisplayOptions(0, ActionBar.DISPLAY_SHOW_CUSTOM);
271         activity.getActionBar().setCustomView(null);
272     }
273 
removeHdcpOptionsForProduction()274     private void removeHdcpOptionsForProduction() {
275         if ("user".equals(Build.TYPE)) {
276             Preference hdcpChecking = findPreference(HDCP_CHECKING_KEY);
277             if (hdcpChecking != null) {
278                 // Remove the preference
279                 getPreferenceScreen().removePreference(hdcpChecking);
280                 mAllPrefs.remove(hdcpChecking);
281             }
282         }
283     }
284 
setPrefsEnabledState(boolean enabled)285     private void setPrefsEnabledState(boolean enabled) {
286         for (int i = 0; i < mAllPrefs.size(); i++) {
287             Preference pref = mAllPrefs.get(i);
288             pref.setEnabled(enabled && !mDisabledPrefs.contains(pref));
289         }
290         updateAllOptions();
291     }
292 
293     @Override
onResume()294     public void onResume() {
295         super.onResume();
296 
297         if (mDpm.getMaximumTimeToLock(null) > 0) {
298             // A DeviceAdmin has specified a maximum time until the device
299             // will lock...  in this case we can't allow the user to turn
300             // on "stay awake when plugged in" because that would defeat the
301             // restriction.
302             mDisabledPrefs.add(mKeepScreenOn);
303         } else {
304             mDisabledPrefs.remove(mKeepScreenOn);
305         }
306 
307         final ContentResolver cr = getActivity().getContentResolver();
308         mLastEnabledState = Settings.Secure.getInt(cr,
309                 Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
310         mEnabledSwitch.setChecked(mLastEnabledState);
311         setPrefsEnabledState(mLastEnabledState);
312 
313         if (mHaveDebugSettings && !mLastEnabledState) {
314             // Overall debugging is disabled, but there are some debug
315             // settings that are enabled.  This is an invalid state.  Switch
316             // to debug settings being enabled, so the user knows there is
317             // stuff enabled and can turn it all off if they want.
318             Settings.Secure.putInt(getActivity().getContentResolver(),
319                     Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED, 1);
320             mLastEnabledState = true;
321             setPrefsEnabledState(mLastEnabledState);
322         }
323     }
324 
updateCheckBox(CheckBoxPreference checkBox, boolean value)325     void updateCheckBox(CheckBoxPreference checkBox, boolean value) {
326         checkBox.setChecked(value);
327         mHaveDebugSettings |= value;
328     }
329 
updateAllOptions()330     private void updateAllOptions() {
331         final Context context = getActivity();
332         final ContentResolver cr = context.getContentResolver();
333         mHaveDebugSettings = false;
334         updateCheckBox(mEnableAdb, Settings.Secure.getInt(cr,
335                 Settings.Secure.ADB_ENABLED, 0) != 0);
336         updateCheckBox(mKeepScreenOn, Settings.System.getInt(cr,
337                 Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
338         updateCheckBox(mEnforceReadExternal, isPermissionEnforced(context, READ_EXTERNAL_STORAGE));
339         updateCheckBox(mAllowMockLocation, Settings.Secure.getInt(cr,
340                 Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0);
341         updateHdcpValues();
342         updatePasswordSummary();
343         updateDebuggerOptions();
344         updateStrictModeVisualOptions();
345         updatePointerLocationOptions();
346         updateShowTouchesOptions();
347         updateFlingerOptions();
348         updateCpuUsageOptions();
349         updateHardwareUiOptions();
350         updateTrackFrameTimeOptions();
351         updateShowHwScreenUpdatesOptions();
352         updateDebugLayoutOptions();
353         updateAnimationScaleOptions();
354         updateEnableTracesOptions();
355         updateImmediatelyDestroyActivitiesOptions();
356         updateAppProcessLimitOptions();
357         updateShowAllANRsOptions();
358     }
359 
resetDangerousOptions()360     private void resetDangerousOptions() {
361         mDontPokeProperties = true;
362         for (int i=0; i<mResetCbPrefs.size(); i++) {
363             CheckBoxPreference cb = mResetCbPrefs.get(i);
364             if (cb.isChecked()) {
365                 cb.setChecked(false);
366                 onPreferenceTreeClick(null, cb);
367             }
368         }
369         resetDebuggerOptions();
370         writeAnimationScaleOption(0, mWindowAnimationScale, null);
371         writeAnimationScaleOption(1, mTransitionAnimationScale, null);
372         writeAnimationScaleOption(2, mAnimatorDurationScale, null);
373         writeEnableTracesOptions(0);
374         writeAppProcessLimitOptions(null);
375         mHaveDebugSettings = false;
376         updateAllOptions();
377         mDontPokeProperties = false;
378         pokeSystemProperties();
379     }
380 
updateHdcpValues()381     private void updateHdcpValues() {
382         int index = 1; // Defaults to drm-only. Needs to match with R.array.hdcp_checking_values
383         ListPreference hdcpChecking = (ListPreference) findPreference(HDCP_CHECKING_KEY);
384         if (hdcpChecking != null) {
385             String currentValue = SystemProperties.get(HDCP_CHECKING_PROPERTY);
386             String[] values = getResources().getStringArray(R.array.hdcp_checking_values);
387             String[] summaries = getResources().getStringArray(R.array.hdcp_checking_summaries);
388             for (int i = 0; i < values.length; i++) {
389                 if (currentValue.equals(values[i])) {
390                     index = i;
391                     break;
392                 }
393             }
394             hdcpChecking.setValue(values[index]);
395             hdcpChecking.setSummary(summaries[index]);
396             hdcpChecking.setOnPreferenceChangeListener(this);
397         }
398     }
399 
updatePasswordSummary()400     private void updatePasswordSummary() {
401         try {
402             if (mBackupManager.hasBackupPassword()) {
403                 mPassword.setSummary(R.string.local_backup_password_summary_change);
404             } else {
405                 mPassword.setSummary(R.string.local_backup_password_summary_none);
406             }
407         } catch (RemoteException e) {
408             // Not much we can do here
409         }
410     }
411 
writeDebuggerOptions()412     private void writeDebuggerOptions() {
413         try {
414             ActivityManagerNative.getDefault().setDebugApp(
415                 mDebugApp, mWaitForDebugger.isChecked(), true);
416         } catch (RemoteException ex) {
417         }
418     }
419 
resetDebuggerOptions()420     private static void resetDebuggerOptions() {
421         try {
422             ActivityManagerNative.getDefault().setDebugApp(
423                     null, false, true);
424         } catch (RemoteException ex) {
425         }
426     }
427 
updateDebuggerOptions()428     private void updateDebuggerOptions() {
429         mDebugApp = Settings.System.getString(
430                 getActivity().getContentResolver(), Settings.System.DEBUG_APP);
431         updateCheckBox(mWaitForDebugger, Settings.System.getInt(
432                 getActivity().getContentResolver(), Settings.System.WAIT_FOR_DEBUGGER, 0) != 0);
433         if (mDebugApp != null && mDebugApp.length() > 0) {
434             String label;
435             try {
436                 ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(mDebugApp,
437                         PackageManager.GET_DISABLED_COMPONENTS);
438                 CharSequence lab = getActivity().getPackageManager().getApplicationLabel(ai);
439                 label = lab != null ? lab.toString() : mDebugApp;
440             } catch (PackageManager.NameNotFoundException e) {
441                 label = mDebugApp;
442             }
443             mDebugAppPref.setSummary(getResources().getString(R.string.debug_app_set, label));
444             mWaitForDebugger.setEnabled(true);
445             mHaveDebugSettings = true;
446         } else {
447             mDebugAppPref.setSummary(getResources().getString(R.string.debug_app_not_set));
448             mWaitForDebugger.setEnabled(false);
449         }
450     }
451 
452     // Returns the current state of the system property that controls
453     // strictmode flashes.  One of:
454     //    0: not explicitly set one way or another
455     //    1: on
456     //    2: off
currentStrictModeActiveIndex()457     private static int currentStrictModeActiveIndex() {
458         if (TextUtils.isEmpty(SystemProperties.get(StrictMode.VISUAL_PROPERTY))) {
459             return 0;
460         }
461         boolean enabled = SystemProperties.getBoolean(StrictMode.VISUAL_PROPERTY, false);
462         return enabled ? 1 : 2;
463     }
464 
writeStrictModeVisualOptions()465     private void writeStrictModeVisualOptions() {
466         try {
467             mWindowManager.setStrictModeVisualIndicatorPreference(mStrictMode.isChecked()
468                     ? "1" : "");
469         } catch (RemoteException e) {
470         }
471     }
472 
updateStrictModeVisualOptions()473     private void updateStrictModeVisualOptions() {
474         updateCheckBox(mStrictMode, currentStrictModeActiveIndex() == 1);
475     }
476 
writePointerLocationOptions()477     private void writePointerLocationOptions() {
478         Settings.System.putInt(getActivity().getContentResolver(),
479                 Settings.System.POINTER_LOCATION, mPointerLocation.isChecked() ? 1 : 0);
480     }
481 
updatePointerLocationOptions()482     private void updatePointerLocationOptions() {
483         updateCheckBox(mPointerLocation, Settings.System.getInt(getActivity().getContentResolver(),
484                 Settings.System.POINTER_LOCATION, 0) != 0);
485     }
486 
writeShowTouchesOptions()487     private void writeShowTouchesOptions() {
488         Settings.System.putInt(getActivity().getContentResolver(),
489                 Settings.System.SHOW_TOUCHES, mShowTouches.isChecked() ? 1 : 0);
490     }
491 
updateShowTouchesOptions()492     private void updateShowTouchesOptions() {
493         updateCheckBox(mShowTouches, Settings.System.getInt(getActivity().getContentResolver(),
494                 Settings.System.SHOW_TOUCHES, 0) != 0);
495     }
496 
updateFlingerOptions()497     private void updateFlingerOptions() {
498         // magic communication with surface flinger.
499         try {
500             IBinder flinger = ServiceManager.getService("SurfaceFlinger");
501             if (flinger != null) {
502                 Parcel data = Parcel.obtain();
503                 Parcel reply = Parcel.obtain();
504                 data.writeInterfaceToken("android.ui.ISurfaceComposer");
505                 flinger.transact(1010, data, reply, 0);
506                 @SuppressWarnings("unused")
507                 int showCpu = reply.readInt();
508                 @SuppressWarnings("unused")
509                 int enableGL = reply.readInt();
510                 int showUpdates = reply.readInt();
511                 updateCheckBox(mShowScreenUpdates, showUpdates != 0);
512                 @SuppressWarnings("unused")
513                 int showBackground = reply.readInt();
514                 int disableOverlays = reply.readInt();
515                 updateCheckBox(mDisableOverlays, disableOverlays != 0);
516                 reply.recycle();
517                 data.recycle();
518             }
519         } catch (RemoteException ex) {
520         }
521     }
522 
writeShowUpdatesOption()523     private void writeShowUpdatesOption() {
524         try {
525             IBinder flinger = ServiceManager.getService("SurfaceFlinger");
526             if (flinger != null) {
527                 Parcel data = Parcel.obtain();
528                 data.writeInterfaceToken("android.ui.ISurfaceComposer");
529                 final int showUpdates = mShowScreenUpdates.isChecked() ? 1 : 0;
530                 data.writeInt(showUpdates);
531                 flinger.transact(1002, data, null, 0);
532                 data.recycle();
533 
534                 updateFlingerOptions();
535             }
536         } catch (RemoteException ex) {
537         }
538     }
539 
writeDisableOverlaysOption()540     private void writeDisableOverlaysOption() {
541         try {
542             IBinder flinger = ServiceManager.getService("SurfaceFlinger");
543             if (flinger != null) {
544                 Parcel data = Parcel.obtain();
545                 data.writeInterfaceToken("android.ui.ISurfaceComposer");
546                 final int disableOverlays = mDisableOverlays.isChecked() ? 1 : 0;
547                 data.writeInt(disableOverlays);
548                 flinger.transact(1008, data, null, 0);
549                 data.recycle();
550 
551                 updateFlingerOptions();
552             }
553         } catch (RemoteException ex) {
554         }
555     }
556 
updateHardwareUiOptions()557     private void updateHardwareUiOptions() {
558         updateCheckBox(mForceHardwareUi, SystemProperties.getBoolean(HARDWARE_UI_PROPERTY, false));
559     }
560 
writeHardwareUiOptions()561     private void writeHardwareUiOptions() {
562         SystemProperties.set(HARDWARE_UI_PROPERTY, mForceHardwareUi.isChecked() ? "true" : "false");
563         pokeSystemProperties();
564     }
565 
updateTrackFrameTimeOptions()566     private void updateTrackFrameTimeOptions() {
567         updateCheckBox(mTrackFrameTime,
568                 SystemProperties.getBoolean(HardwareRenderer.PROFILE_PROPERTY, false));
569     }
570 
writeTrackFrameTimeOptions()571     private void writeTrackFrameTimeOptions() {
572         SystemProperties.set(HardwareRenderer.PROFILE_PROPERTY,
573                 mTrackFrameTime.isChecked() ? "true" : "false");
574         pokeSystemProperties();
575     }
576 
updateShowHwScreenUpdatesOptions()577     private void updateShowHwScreenUpdatesOptions() {
578         updateCheckBox(mShowHwScreenUpdates,
579                 SystemProperties.getBoolean(HardwareRenderer.DEBUG_DIRTY_REGIONS_PROPERTY, false));
580     }
581 
writeShowHwScreenUpdatesOptions()582     private void writeShowHwScreenUpdatesOptions() {
583         SystemProperties.set(HardwareRenderer.DEBUG_DIRTY_REGIONS_PROPERTY,
584                 mShowHwScreenUpdates.isChecked() ? "true" : "false");
585         pokeSystemProperties();
586     }
587 
updateDebugLayoutOptions()588     private void updateDebugLayoutOptions() {
589         updateCheckBox(mDebugLayout,
590                 SystemProperties.getBoolean(View.DEBUG_LAYOUT_PROPERTY, false));
591     }
592 
writeDebugLayoutOptions()593     private void writeDebugLayoutOptions() {
594         SystemProperties.set(View.DEBUG_LAYOUT_PROPERTY,
595                 mDebugLayout.isChecked() ? "true" : "false");
596         pokeSystemProperties();
597     }
598 
updateCpuUsageOptions()599     private void updateCpuUsageOptions() {
600         updateCheckBox(mShowCpuUsage, Settings.System.getInt(getActivity().getContentResolver(),
601                 Settings.System.SHOW_PROCESSES, 0) != 0);
602     }
603 
writeCpuUsageOptions()604     private void writeCpuUsageOptions() {
605         boolean value = mShowCpuUsage.isChecked();
606         Settings.System.putInt(getActivity().getContentResolver(),
607                 Settings.System.SHOW_PROCESSES, value ? 1 : 0);
608         Intent service = (new Intent())
609                 .setClassName("com.android.systemui", "com.android.systemui.LoadAverageService");
610         if (value) {
611             getActivity().startService(service);
612         } else {
613             getActivity().stopService(service);
614         }
615     }
616 
writeImmediatelyDestroyActivitiesOptions()617     private void writeImmediatelyDestroyActivitiesOptions() {
618         try {
619             ActivityManagerNative.getDefault().setAlwaysFinish(
620                     mImmediatelyDestroyActivities.isChecked());
621         } catch (RemoteException ex) {
622         }
623     }
624 
updateImmediatelyDestroyActivitiesOptions()625     private void updateImmediatelyDestroyActivitiesOptions() {
626         updateCheckBox(mImmediatelyDestroyActivities, Settings.System.getInt(
627             getActivity().getContentResolver(), Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0);
628     }
629 
updateAnimationScaleValue(int which, ListPreference pref)630     private void updateAnimationScaleValue(int which, ListPreference pref) {
631         try {
632             float scale = mWindowManager.getAnimationScale(which);
633             if (scale != 1) {
634                 mHaveDebugSettings = true;
635             }
636             CharSequence[] values = pref.getEntryValues();
637             for (int i=0; i<values.length; i++) {
638                 float val = Float.parseFloat(values[i].toString());
639                 if (scale <= val) {
640                     pref.setValueIndex(i);
641                     pref.setSummary(pref.getEntries()[i]);
642                     return;
643                 }
644             }
645             pref.setValueIndex(values.length-1);
646             pref.setSummary(pref.getEntries()[0]);
647         } catch (RemoteException e) {
648         }
649     }
650 
updateAnimationScaleOptions()651     private void updateAnimationScaleOptions() {
652         updateAnimationScaleValue(0, mWindowAnimationScale);
653         updateAnimationScaleValue(1, mTransitionAnimationScale);
654         updateAnimationScaleValue(2, mAnimatorDurationScale);
655     }
656 
writeAnimationScaleOption(int which, ListPreference pref, Object newValue)657     private void writeAnimationScaleOption(int which, ListPreference pref, Object newValue) {
658         try {
659             float scale = newValue != null ? Float.parseFloat(newValue.toString()) : 1;
660             mWindowManager.setAnimationScale(which, scale);
661             updateAnimationScaleValue(which, pref);
662         } catch (RemoteException e) {
663         }
664     }
665 
updateAppProcessLimitOptions()666     private void updateAppProcessLimitOptions() {
667         try {
668             int limit = ActivityManagerNative.getDefault().getProcessLimit();
669             CharSequence[] values = mAppProcessLimit.getEntryValues();
670             for (int i=0; i<values.length; i++) {
671                 int val = Integer.parseInt(values[i].toString());
672                 if (val >= limit) {
673                     if (i != 0) {
674                         mHaveDebugSettings = true;
675                     }
676                     mAppProcessLimit.setValueIndex(i);
677                     mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[i]);
678                     return;
679                 }
680             }
681             mAppProcessLimit.setValueIndex(0);
682             mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[0]);
683         } catch (RemoteException e) {
684         }
685     }
686 
writeAppProcessLimitOptions(Object newValue)687     private void writeAppProcessLimitOptions(Object newValue) {
688         try {
689             int limit = newValue != null ? Integer.parseInt(newValue.toString()) : -1;
690             ActivityManagerNative.getDefault().setProcessLimit(limit);
691             updateAppProcessLimitOptions();
692         } catch (RemoteException e) {
693         }
694     }
695 
writeShowAllANRsOptions()696     private void writeShowAllANRsOptions() {
697         Settings.Secure.putInt(getActivity().getContentResolver(),
698                 Settings.Secure.ANR_SHOW_BACKGROUND,
699                 mShowAllANRs.isChecked() ? 1 : 0);
700     }
701 
updateShowAllANRsOptions()702     private void updateShowAllANRsOptions() {
703         updateCheckBox(mShowAllANRs, Settings.Secure.getInt(
704             getActivity().getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0);
705     }
706 
updateEnableTracesOptions()707     private void updateEnableTracesOptions() {
708         String strValue = SystemProperties.get(Trace.PROPERTY_TRACE_TAG_ENABLEFLAGS);
709         long flags = SystemProperties.getLong(Trace.PROPERTY_TRACE_TAG_ENABLEFLAGS, 0);
710         String[] values = mEnableTracesPref.getEntryValues();
711         int numSet = 0;
712         for (int i=Trace.TRACE_FLAGS_START_BIT; i<values.length; i++) {
713             boolean set = (flags&(1<<i)) != 0;
714             mEnableTracesPref.setValue(i-Trace.TRACE_FLAGS_START_BIT, set);
715             if (set) {
716                 numSet++;
717             }
718         }
719         if (numSet == 0) {
720             mEnableTracesPref.setSummary(R.string.enable_traces_summary_none);
721         } else if (numSet == values.length) {
722             mHaveDebugSettings = true;
723             mEnableTracesPref.setSummary(R.string.enable_traces_summary_all);
724         } else {
725             mHaveDebugSettings = true;
726             mEnableTracesPref.setSummary(getString(R.string.enable_traces_summary_num, numSet));
727         }
728     }
729 
writeEnableTracesOptions()730     private void writeEnableTracesOptions() {
731         long value = 0;
732         String[] values = mEnableTracesPref.getEntryValues();
733         for (int i=Trace.TRACE_FLAGS_START_BIT; i<values.length; i++) {
734             if (mEnableTracesPref.getValue(i-Trace.TRACE_FLAGS_START_BIT)) {
735                 value |= 1<<i;
736             }
737         }
738         writeEnableTracesOptions(value);
739         // Make sure summary is updated.
740         updateEnableTracesOptions();
741     }
742 
writeEnableTracesOptions(long value)743     private void writeEnableTracesOptions(long value) {
744         SystemProperties.set(Trace.PROPERTY_TRACE_TAG_ENABLEFLAGS,
745                 "0x" + Long.toString(value, 16));
746         pokeSystemProperties();
747     }
748 
749     @Override
onCheckedChanged(CompoundButton buttonView, boolean isChecked)750     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
751         if (buttonView == mEnabledSwitch) {
752             if (isChecked != mLastEnabledState) {
753                 if (isChecked) {
754                     mDialogClicked = false;
755                     if (mEnableDialog != null) dismissDialogs();
756                     mEnableDialog = new AlertDialog.Builder(getActivity()).setMessage(
757                             getActivity().getResources().getString(
758                                     R.string.dev_settings_warning_message))
759                             .setTitle(R.string.dev_settings_warning_title)
760                             .setIcon(android.R.drawable.ic_dialog_alert)
761                             .setPositiveButton(android.R.string.yes, this)
762                             .setNegativeButton(android.R.string.no, this)
763                             .show();
764                     mEnableDialog.setOnDismissListener(this);
765                 } else {
766                     resetDangerousOptions();
767                     Settings.Secure.putInt(getActivity().getContentResolver(),
768                             Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED, 0);
769                     mLastEnabledState = isChecked;
770                     setPrefsEnabledState(mLastEnabledState);
771                 }
772             }
773         }
774     }
775 
776     @Override
onActivityResult(int requestCode, int resultCode, Intent data)777     public void onActivityResult(int requestCode, int resultCode, Intent data) {
778         if (requestCode == RESULT_DEBUG_APP) {
779             if (resultCode == Activity.RESULT_OK) {
780                 mDebugApp = data.getAction();
781                 writeDebuggerOptions();
782                 updateDebuggerOptions();
783             }
784         } else {
785             super.onActivityResult(requestCode, resultCode, data);
786         }
787     }
788 
789     @Override
onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)790     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
791 
792         if (Utils.isMonkeyRunning()) {
793             return false;
794         }
795 
796         if (preference == mEnableAdb) {
797             if (mEnableAdb.isChecked()) {
798                 mDialogClicked = false;
799                 if (mAdbDialog != null) dismissDialogs();
800                 mAdbDialog = new AlertDialog.Builder(getActivity()).setMessage(
801                         getActivity().getResources().getString(R.string.adb_warning_message))
802                         .setTitle(R.string.adb_warning_title)
803                         .setIcon(android.R.drawable.ic_dialog_alert)
804                         .setPositiveButton(android.R.string.yes, this)
805                         .setNegativeButton(android.R.string.no, this)
806                         .show();
807                 mAdbDialog.setOnDismissListener(this);
808             } else {
809                 Settings.Secure.putInt(getActivity().getContentResolver(),
810                         Settings.Secure.ADB_ENABLED, 0);
811             }
812         } else if (preference == mKeepScreenOn) {
813             Settings.System.putInt(getActivity().getContentResolver(),
814                     Settings.System.STAY_ON_WHILE_PLUGGED_IN,
815                     mKeepScreenOn.isChecked() ?
816                     (BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB) : 0);
817         } else if (preference == mEnforceReadExternal) {
818             if (mEnforceReadExternal.isChecked()) {
819                 ConfirmEnforceFragment.show(this);
820             } else {
821                 setPermissionEnforced(getActivity(), READ_EXTERNAL_STORAGE, false);
822             }
823         } else if (preference == mAllowMockLocation) {
824             Settings.Secure.putInt(getActivity().getContentResolver(),
825                     Settings.Secure.ALLOW_MOCK_LOCATION,
826                     mAllowMockLocation.isChecked() ? 1 : 0);
827         } else if (preference == mDebugAppPref) {
828             startActivityForResult(new Intent(getActivity(), AppPicker.class), RESULT_DEBUG_APP);
829         } else if (preference == mWaitForDebugger) {
830             writeDebuggerOptions();
831         } else if (preference == mStrictMode) {
832             writeStrictModeVisualOptions();
833         } else if (preference == mPointerLocation) {
834             writePointerLocationOptions();
835         } else if (preference == mShowTouches) {
836             writeShowTouchesOptions();
837         } else if (preference == mShowScreenUpdates) {
838             writeShowUpdatesOption();
839         } else if (preference == mDisableOverlays) {
840             writeDisableOverlaysOption();
841         } else if (preference == mShowCpuUsage) {
842             writeCpuUsageOptions();
843         } else if (preference == mImmediatelyDestroyActivities) {
844             writeImmediatelyDestroyActivitiesOptions();
845         } else if (preference == mShowAllANRs) {
846             writeShowAllANRsOptions();
847         } else if (preference == mForceHardwareUi) {
848             writeHardwareUiOptions();
849         } else if (preference == mTrackFrameTime) {
850             writeTrackFrameTimeOptions();
851         } else if (preference == mShowHwScreenUpdates) {
852             writeShowHwScreenUpdatesOptions();
853         } else if (preference == mDebugLayout) {
854             writeDebugLayoutOptions();
855         }
856 
857         return false;
858     }
859 
860     @Override
onPreferenceChange(Preference preference, Object newValue)861     public boolean onPreferenceChange(Preference preference, Object newValue) {
862         if (HDCP_CHECKING_KEY.equals(preference.getKey())) {
863             SystemProperties.set(HDCP_CHECKING_PROPERTY, newValue.toString());
864             updateHdcpValues();
865             pokeSystemProperties();
866             return true;
867         } else if (preference == mWindowAnimationScale) {
868             writeAnimationScaleOption(0, mWindowAnimationScale, newValue);
869             return true;
870         } else if (preference == mTransitionAnimationScale) {
871             writeAnimationScaleOption(1, mTransitionAnimationScale, newValue);
872             return true;
873         } else if (preference == mAnimatorDurationScale) {
874             writeAnimationScaleOption(2, mAnimatorDurationScale, newValue);
875             return true;
876         } else if (preference == mEnableTracesPref) {
877             writeEnableTracesOptions();
878             return true;
879         } else if (preference == mAppProcessLimit) {
880             writeAppProcessLimitOptions(newValue);
881             return true;
882         }
883         return false;
884     }
885 
dismissDialogs()886     private void dismissDialogs() {
887         if (mAdbDialog != null) {
888             mAdbDialog.dismiss();
889             mAdbDialog = null;
890         }
891         if (mEnableDialog != null) {
892             mEnableDialog.dismiss();
893             mEnableDialog = null;
894         }
895     }
896 
onClick(DialogInterface dialog, int which)897     public void onClick(DialogInterface dialog, int which) {
898         if (dialog == mAdbDialog) {
899             if (which == DialogInterface.BUTTON_POSITIVE) {
900                 mDialogClicked = true;
901                 Settings.Secure.putInt(getActivity().getContentResolver(),
902                         Settings.Secure.ADB_ENABLED, 1);
903             } else {
904                 // Reset the toggle
905                 mEnableAdb.setChecked(false);
906             }
907         } else if (dialog == mEnableDialog) {
908             if (which == DialogInterface.BUTTON_POSITIVE) {
909                 mDialogClicked = true;
910                 Settings.Secure.putInt(getActivity().getContentResolver(),
911                         Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED, 1);
912                 mLastEnabledState = true;
913                 setPrefsEnabledState(mLastEnabledState);
914             } else {
915                 // Reset the toggle
916                 mEnabledSwitch.setChecked(false);
917             }
918         }
919     }
920 
onDismiss(DialogInterface dialog)921     public void onDismiss(DialogInterface dialog) {
922         // Assuming that onClick gets called first
923         if (dialog == mAdbDialog) {
924             if (!mDialogClicked) {
925                 mEnableAdb.setChecked(false);
926             }
927             mAdbDialog = null;
928         } else if (dialog == mEnableDialog) {
929             if (!mDialogClicked) {
930                 mEnabledSwitch.setChecked(false);
931             }
932             mEnableDialog = null;
933         }
934     }
935 
936     @Override
onDestroy()937     public void onDestroy() {
938         dismissDialogs();
939         super.onDestroy();
940     }
941 
pokeSystemProperties()942     void pokeSystemProperties() {
943         if (!mDontPokeProperties) {
944             (new SystemPropPoker()).execute();
945         }
946     }
947 
948     static class SystemPropPoker extends AsyncTask<Void, Void, Void> {
949         @Override
doInBackground(Void... params)950         protected Void doInBackground(Void... params) {
951             String[] services;
952             try {
953                 services = ServiceManager.listServices();
954             } catch (RemoteException e) {
955                 return null;
956             }
957             for (String service : services) {
958                 IBinder obj = ServiceManager.checkService(service);
959                 if (obj != null) {
960                     Parcel data = Parcel.obtain();
961                     try {
962                         obj.transact(IBinder.SYSPROPS_TRANSACTION, data, null, 0);
963                     } catch (RemoteException e) {
964                     }
965                     data.recycle();
966                 }
967             }
968             return null;
969         }
970     }
971 
972     /**
973      * Dialog to confirm enforcement of {@link #READ_EXTERNAL_STORAGE}.
974      */
975     public static class ConfirmEnforceFragment extends DialogFragment {
show(DevelopmentSettings parent)976         public static void show(DevelopmentSettings parent) {
977             final ConfirmEnforceFragment dialog = new ConfirmEnforceFragment();
978             dialog.setTargetFragment(parent, 0);
979             dialog.show(parent.getFragmentManager(), TAG_CONFIRM_ENFORCE);
980         }
981 
982         @Override
onCreateDialog(Bundle savedInstanceState)983         public Dialog onCreateDialog(Bundle savedInstanceState) {
984             final Context context = getActivity();
985 
986             final AlertDialog.Builder builder = new AlertDialog.Builder(context);
987             builder.setTitle(R.string.enforce_read_external_confirm_title);
988             builder.setMessage(R.string.enforce_read_external_confirm_message);
989 
990             builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
991                 @Override
992                 public void onClick(DialogInterface dialog, int which) {
993                     setPermissionEnforced(context, READ_EXTERNAL_STORAGE, true);
994                     ((DevelopmentSettings) getTargetFragment()).updateAllOptions();
995                 }
996             });
997             builder.setNegativeButton(android.R.string.cancel, new OnClickListener() {
998                 @Override
999                 public void onClick(DialogInterface dialog, int which) {
1000                     ((DevelopmentSettings) getTargetFragment()).updateAllOptions();
1001                 }
1002             });
1003 
1004             return builder.create();
1005         }
1006     }
1007 
isPermissionEnforced(Context context, String permission)1008     private static boolean isPermissionEnforced(Context context, String permission) {
1009         try {
1010             return ActivityThread.getPackageManager().isPermissionEnforced(READ_EXTERNAL_STORAGE);
1011         } catch (RemoteException e) {
1012             throw new RuntimeException("Problem talking with PackageManager", e);
1013         }
1014     }
1015 
setPermissionEnforced( Context context, String permission, boolean enforced)1016     private static void setPermissionEnforced(
1017             Context context, String permission, boolean enforced) {
1018         try {
1019             // TODO: offload to background thread
1020             ActivityThread.getPackageManager()
1021                     .setPermissionEnforced(READ_EXTERNAL_STORAGE, enforced);
1022         } catch (RemoteException e) {
1023             throw new RuntimeException("Problem talking with PackageManager", e);
1024         }
1025     }
1026 }
1027