DevelopmentSettings.java revision 83b09a57e158f3050c7feb5ea75e8dd2d626697e
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
17package com.android.settings;
18
19import android.app.ActivityManagerNative;
20import android.app.AlertDialog;
21import android.app.Dialog;
22import android.content.ContentResolver;
23import android.content.DialogInterface;
24import android.content.Intent;
25import android.os.BatteryManager;
26import android.os.Build;
27import android.os.Bundle;
28import android.os.IBinder;
29import android.os.Parcel;
30import android.os.RemoteException;
31import android.os.ServiceManager;
32import android.os.StrictMode;
33import android.os.SystemProperties;
34import android.preference.CheckBoxPreference;
35import android.preference.ListPreference;
36import android.preference.Preference;
37import android.preference.PreferenceFragment;
38import android.preference.PreferenceScreen;
39import android.preference.Preference.OnPreferenceChangeListener;
40import android.provider.Settings;
41import android.text.TextUtils;
42import android.view.IWindowManager;
43
44/*
45 * Displays preferences for application developers.
46 */
47public class DevelopmentSettings extends PreferenceFragment
48        implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
49                OnPreferenceChangeListener {
50
51    private static final String ENABLE_ADB = "enable_adb";
52    private static final String KEEP_SCREEN_ON = "keep_screen_on";
53    private static final String ALLOW_MOCK_LOCATION = "allow_mock_location";
54    private static final String HDCP_CHECKING_KEY = "hdcp_checking";
55    private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
56
57    private static final String STRICT_MODE_KEY = "strict_mode";
58    private static final String POINTER_LOCATION_KEY = "pointer_location";
59    private static final String SHOW_SCREEN_UPDATES_KEY = "show_screen_updates";
60    private static final String SHOW_CPU_USAGE_KEY = "show_cpu_usage";
61    private static final String WINDOW_ANIMATION_SCALE_KEY = "window_animation_scale";
62    private static final String TRANSITION_ANIMATION_SCALE_KEY = "transition_animation_scale";
63
64    private static final String IMMEDIATELY_DESTROY_ACTIVITIES_KEY
65            = "immediately_destroy_activities";
66    private static final String APP_PROCESS_LIMIT_KEY = "app_process_limit";
67
68    private IWindowManager mWindowManager;
69
70    private CheckBoxPreference mEnableAdb;
71    private CheckBoxPreference mKeepScreenOn;
72    private CheckBoxPreference mAllowMockLocation;
73
74    private CheckBoxPreference mStrictMode;
75    private CheckBoxPreference mPointerLocation;
76    private CheckBoxPreference mShowScreenUpdates;
77    private CheckBoxPreference mShowCpuUsage;
78    private ListPreference mWindowAnimationScale;
79    private ListPreference mTransitionAnimationScale;
80
81    private CheckBoxPreference mImmediatelyDestroyActivities;
82    private ListPreference mAppProcessLimit;
83
84    // To track whether Yes was clicked in the adb warning dialog
85    private boolean mOkClicked;
86
87    private Dialog mOkDialog;
88
89    @Override
90    public void onCreate(Bundle icicle) {
91        super.onCreate(icicle);
92
93        mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
94
95        addPreferencesFromResource(R.xml.development_prefs);
96
97        mEnableAdb = (CheckBoxPreference) findPreference(ENABLE_ADB);
98        mKeepScreenOn = (CheckBoxPreference) findPreference(KEEP_SCREEN_ON);
99        mAllowMockLocation = (CheckBoxPreference) findPreference(ALLOW_MOCK_LOCATION);
100
101        mStrictMode = (CheckBoxPreference) findPreference(STRICT_MODE_KEY);
102        mPointerLocation = (CheckBoxPreference) findPreference(POINTER_LOCATION_KEY);
103        mShowScreenUpdates = (CheckBoxPreference) findPreference(SHOW_SCREEN_UPDATES_KEY);
104        mShowCpuUsage = (CheckBoxPreference) findPreference(SHOW_CPU_USAGE_KEY);
105        mWindowAnimationScale = (ListPreference) findPreference(WINDOW_ANIMATION_SCALE_KEY);
106        mWindowAnimationScale.setOnPreferenceChangeListener(this);
107        mTransitionAnimationScale = (ListPreference) findPreference(TRANSITION_ANIMATION_SCALE_KEY);
108        mTransitionAnimationScale.setOnPreferenceChangeListener(this);
109
110        mImmediatelyDestroyActivities = (CheckBoxPreference) findPreference(
111                IMMEDIATELY_DESTROY_ACTIVITIES_KEY);
112        mAppProcessLimit = (ListPreference) findPreference(APP_PROCESS_LIMIT_KEY);
113        mAppProcessLimit.setOnPreferenceChangeListener(this);
114
115        removeHdcpOptionsForProduction();
116    }
117
118    private void removeHdcpOptionsForProduction() {
119        if ("user".equals(Build.TYPE)) {
120            Preference hdcpChecking = findPreference(HDCP_CHECKING_KEY);
121            if (hdcpChecking != null) {
122                // Remove the preference
123                getPreferenceScreen().removePreference(hdcpChecking);
124            }
125        }
126    }
127
128    @Override
129    public void onResume() {
130        super.onResume();
131
132        final ContentResolver cr = getActivity().getContentResolver();
133        mEnableAdb.setChecked(Settings.Secure.getInt(cr,
134                Settings.Secure.ADB_ENABLED, 0) != 0);
135        mKeepScreenOn.setChecked(Settings.System.getInt(cr,
136                Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
137        mAllowMockLocation.setChecked(Settings.Secure.getInt(cr,
138                Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0);
139        updateHdcpValues();
140        updateStrictModeVisualOptions();
141        updatePointerLocationOptions();
142        updateFlingerOptions();
143        updateCpuUsageOptions();
144        updateAnimationScaleOptions();
145        updateImmediatelyDestroyActivitiesOptions();
146        updateAppProcessLimitOptions();
147    }
148
149    private void updateHdcpValues() {
150        int index = 1; // Defaults to drm-only. Needs to match with R.array.hdcp_checking_values
151        ListPreference hdcpChecking = (ListPreference) findPreference(HDCP_CHECKING_KEY);
152        if (hdcpChecking != null) {
153            String currentValue = SystemProperties.get(HDCP_CHECKING_PROPERTY);
154            String[] values = getResources().getStringArray(R.array.hdcp_checking_values);
155            String[] summaries = getResources().getStringArray(R.array.hdcp_checking_summaries);
156            for (int i = 0; i < values.length; i++) {
157                if (currentValue.equals(values[i])) {
158                    index = i;
159                    break;
160                }
161            }
162            hdcpChecking.setValue(values[index]);
163            hdcpChecking.setSummary(summaries[index]);
164            hdcpChecking.setOnPreferenceChangeListener(this);
165        }
166    }
167
168    // Returns the current state of the system property that controls
169    // strictmode flashes.  One of:
170    //    0: not explicitly set one way or another
171    //    1: on
172    //    2: off
173    private int currentStrictModeActiveIndex() {
174        if (TextUtils.isEmpty(SystemProperties.get(StrictMode.VISUAL_PROPERTY))) {
175            return 0;
176        }
177        boolean enabled = SystemProperties.getBoolean(StrictMode.VISUAL_PROPERTY, false);
178        return enabled ? 1 : 2;
179    }
180
181    private void writeStrictModeVisualOptions() {
182        try {
183            mWindowManager.setStrictModeVisualIndicatorPreference(mStrictMode.isChecked()
184                    ? "1" : "");
185        } catch (RemoteException e) {
186        }
187    }
188
189    private void updateStrictModeVisualOptions() {
190        mStrictMode.setChecked(currentStrictModeActiveIndex() == 1);
191    }
192
193    private void writePointerLocationOptions() {
194        Settings.System.putInt(getActivity().getContentResolver(),
195                Settings.System.POINTER_LOCATION, mPointerLocation.isChecked() ? 1 : 0);
196    }
197
198    private void updatePointerLocationOptions() {
199        mPointerLocation.setChecked(Settings.System.getInt(getActivity().getContentResolver(),
200                Settings.System.POINTER_LOCATION, 0) != 0);
201    }
202
203    private void updateFlingerOptions() {
204        // magic communication with surface flinger.
205        try {
206            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
207            if (flinger != null) {
208                Parcel data = Parcel.obtain();
209                Parcel reply = Parcel.obtain();
210                data.writeInterfaceToken("android.ui.ISurfaceComposer");
211                flinger.transact(1010, data, reply, 0);
212                @SuppressWarnings("unused")
213                int showCpu = reply.readInt();
214                @SuppressWarnings("unused")
215                int enableGL = reply.readInt();
216                int showUpdates = reply.readInt();
217                mShowScreenUpdates.setChecked(showUpdates != 0);
218                @SuppressWarnings("unused")
219                int showBackground = reply.readInt();
220                reply.recycle();
221                data.recycle();
222            }
223        } catch (RemoteException ex) {
224        }
225    }
226
227    private void writeFlingerOptions() {
228        try {
229            IBinder flinger = ServiceManager.getService("SurfaceFlinger");
230            if (flinger != null) {
231                Parcel data = Parcel.obtain();
232                data.writeInterfaceToken("android.ui.ISurfaceComposer");
233                data.writeInt(mShowScreenUpdates.isChecked() ? 1 : 0);
234                flinger.transact(1002, data, null, 0);
235                data.recycle();
236
237                updateFlingerOptions();
238            }
239        } catch (RemoteException ex) {
240        }
241    }
242
243    private void updateCpuUsageOptions() {
244        mShowCpuUsage.setChecked(Settings.System.getInt(getActivity().getContentResolver(),
245                Settings.System.SHOW_PROCESSES, 0) != 0);
246    }
247
248    private void writeCpuUsageOptions() {
249        boolean value = mShowCpuUsage.isChecked();
250        Settings.System.putInt(getActivity().getContentResolver(),
251                Settings.System.SHOW_PROCESSES, value ? 1 : 0);
252        Intent service = (new Intent())
253                .setClassName("android", "com.android.server.LoadAverageService");
254        if (value) {
255            getActivity().startService(service);
256        } else {
257            getActivity().stopService(service);
258        }
259    }
260
261    private void writeImmediatelyDestroyActivitiesOptions() {
262        try {
263            ActivityManagerNative.getDefault().setAlwaysFinish(
264                    mImmediatelyDestroyActivities.isChecked());
265        } catch (RemoteException ex) {
266        }
267    }
268
269    private void updateImmediatelyDestroyActivitiesOptions() {
270        mImmediatelyDestroyActivities.setChecked(Settings.System.getInt(
271            getActivity().getContentResolver(), Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0);
272    }
273
274    private void updateAnimationScaleValue(int which, ListPreference pref) {
275        try {
276            float scale = mWindowManager.getAnimationScale(which);
277            CharSequence[] values = pref.getEntryValues();
278            for (int i=0; i<values.length; i++) {
279                float val = Float.parseFloat(values[i].toString());
280                if (scale <= val) {
281                    pref.setValueIndex(i);
282                    pref.setSummary(pref.getEntries()[i]);
283                    return;
284                }
285            }
286            pref.setValueIndex(values.length-1);
287            pref.setSummary(pref.getEntries()[0]);
288        } catch (RemoteException e) {
289        }
290    }
291
292    private void updateAnimationScaleOptions() {
293        updateAnimationScaleValue(0, mWindowAnimationScale);
294        updateAnimationScaleValue(1, mTransitionAnimationScale);
295    }
296
297    private void writeAnimationScaleOption(int which, ListPreference pref, Object newValue) {
298        try {
299            float scale = Float.parseFloat(newValue.toString());
300            mWindowManager.setAnimationScale(which, scale);
301        } catch (RemoteException e) {
302        }
303    }
304
305    private void updateAppProcessLimitOptions() {
306        try {
307            int limit = ActivityManagerNative.getDefault().getProcessLimit();
308            CharSequence[] values = mAppProcessLimit.getEntryValues();
309            for (int i=0; i<values.length; i++) {
310                int val = Integer.parseInt(values[i].toString());
311                if (val >= limit) {
312                    mAppProcessLimit.setValueIndex(i);
313                    mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[i]);
314                    return;
315                }
316            }
317            mAppProcessLimit.setValueIndex(0);
318            mAppProcessLimit.setSummary(mAppProcessLimit.getEntries()[0]);
319        } catch (RemoteException e) {
320        }
321    }
322
323    private void writeAppProcessLimitOptions(Object newValue) {
324        try {
325            int limit = Integer.parseInt(newValue.toString());
326            ActivityManagerNative.getDefault().setProcessLimit(limit);
327        } catch (RemoteException e) {
328        }
329    }
330
331    @Override
332    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
333
334        if (Utils.isMonkeyRunning()) {
335            return false;
336        }
337
338        if (preference == mEnableAdb) {
339            if (mEnableAdb.isChecked()) {
340                mOkClicked = false;
341                if (mOkDialog != null) dismissDialog();
342                mOkDialog = new AlertDialog.Builder(getActivity()).setMessage(
343                        getActivity().getResources().getString(R.string.adb_warning_message))
344                        .setTitle(R.string.adb_warning_title)
345                        .setIcon(android.R.drawable.ic_dialog_alert)
346                        .setPositiveButton(android.R.string.yes, this)
347                        .setNegativeButton(android.R.string.no, this)
348                        .show();
349                mOkDialog.setOnDismissListener(this);
350            } else {
351                Settings.Secure.putInt(getActivity().getContentResolver(),
352                        Settings.Secure.ADB_ENABLED, 0);
353            }
354        } else if (preference == mKeepScreenOn) {
355            Settings.System.putInt(getActivity().getContentResolver(),
356                    Settings.System.STAY_ON_WHILE_PLUGGED_IN,
357                    mKeepScreenOn.isChecked() ?
358                    (BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB) : 0);
359        } else if (preference == mAllowMockLocation) {
360            Settings.Secure.putInt(getActivity().getContentResolver(),
361                    Settings.Secure.ALLOW_MOCK_LOCATION,
362                    mAllowMockLocation.isChecked() ? 1 : 0);
363        } else if (preference == mStrictMode) {
364            writeStrictModeVisualOptions();
365        } else if (preference == mPointerLocation) {
366            writePointerLocationOptions();
367        } else if (preference == mShowScreenUpdates) {
368            writeFlingerOptions();
369        } else if (preference == mShowCpuUsage) {
370            writeCpuUsageOptions();
371        } else if (preference == mImmediatelyDestroyActivities) {
372            writeImmediatelyDestroyActivitiesOptions();
373        }
374
375        return false;
376    }
377
378    @Override
379    public boolean onPreferenceChange(Preference preference, Object newValue) {
380        if (HDCP_CHECKING_KEY.equals(preference.getKey())) {
381            SystemProperties.set(HDCP_CHECKING_PROPERTY, newValue.toString());
382            updateHdcpValues();
383            return true;
384        } else if (preference == mWindowAnimationScale) {
385            writeAnimationScaleOption(0, mWindowAnimationScale, newValue);
386            return true;
387        } else if (preference == mTransitionAnimationScale) {
388            writeAnimationScaleOption(1, mTransitionAnimationScale, newValue);
389            return true;
390        } else if (preference == mAppProcessLimit) {
391            writeAppProcessLimitOptions(newValue);
392            return true;
393        }
394        return false;
395    }
396
397    private void dismissDialog() {
398        if (mOkDialog == null) return;
399        mOkDialog.dismiss();
400        mOkDialog = null;
401    }
402
403    public void onClick(DialogInterface dialog, int which) {
404        if (which == DialogInterface.BUTTON_POSITIVE) {
405            mOkClicked = true;
406            Settings.Secure.putInt(getActivity().getContentResolver(),
407                    Settings.Secure.ADB_ENABLED, 1);
408        } else {
409            // Reset the toggle
410            mEnableAdb.setChecked(false);
411        }
412    }
413
414    public void onDismiss(DialogInterface dialog) {
415        // Assuming that onClick gets called first
416        if (!mOkClicked) {
417            mEnableAdb.setChecked(false);
418        }
419    }
420
421    @Override
422    public void onDestroy() {
423        dismissDialog();
424        super.onDestroy();
425    }
426}
427