OSDN Git Service

95a354d261a35a1290c46bb0d9ce50e02db18711
[android-x86/packages-apps-Settings.git] / src / com / android / settings / notificationlight / NotificationLightSettings.java
1 /*
2  * Copyright (C) 2012 The CyanogenMod 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.notificationlight;
18
19 import android.app.AlertDialog;
20 import android.app.Dialog;
21 import android.content.ContentResolver;
22 import android.content.Context;
23 import android.content.DialogInterface;
24 import android.content.pm.PackageInfo;
25 import android.content.pm.PackageManager;
26 import android.content.pm.PackageManager.NameNotFoundException;
27 import android.content.res.Resources;
28 import android.graphics.drawable.Drawable;
29 import android.os.Bundle;
30 import android.preference.Preference;
31 import android.preference.PreferenceGroup;
32 import android.preference.PreferenceScreen;
33 import android.provider.Settings;
34 import android.telephony.TelephonyManager;
35 import android.text.TextUtils;
36 import android.view.Menu;
37 import android.view.MenuInflater;
38 import android.view.MenuItem;
39 import android.view.View;
40 import android.widget.AdapterView;
41 import android.widget.AdapterView.OnItemClickListener;
42 import android.widget.ListView;
43
44 import com.android.settings.R;
45 import com.android.settings.SettingsPreferenceFragment;
46 import com.android.settings.cyanogenmod.CMSystemSettingSwitchPreference;
47 import com.android.settings.cyanogenmod.PackageListAdapter;
48 import com.android.settings.cyanogenmod.PackageListAdapter.PackageItem;
49 import com.android.settings.cyanogenmod.SystemSettingSwitchPreference;
50
51 import org.cyanogenmod.internal.logging.CMMetricsLogger;
52
53 import java.util.ArrayList;
54 import java.util.HashMap;
55 import java.util.List;
56 import java.util.Map;
57
58 import cyanogenmod.providers.CMSettings;
59 import cyanogenmod.util.ColorUtils;
60
61 public class NotificationLightSettings extends SettingsPreferenceFragment implements
62         Preference.OnPreferenceChangeListener, AdapterView.OnItemLongClickListener {
63     private static final String TAG = "NotificationLightSettings";
64     private static final String DEFAULT_PREF = "default";
65     private static final String MISSED_CALL_PREF = "missed_call";
66     private static final String VOICEMAIL_PREF = "voicemail";
67     public static final int ACTION_TEST = 0;
68     public static final int ACTION_DELETE = 1;
69     private static final int MENU_ADD = 0;
70     private static final int DIALOG_APPS = 0;
71
72     private int mDefaultColor;
73     private int mDefaultLedOn;
74     private int mDefaultLedOff;
75     private PackageManager mPackageManager;
76     private PreferenceGroup mApplicationPrefList;
77     private PreferenceScreen mNotificationLedBrightnessPref;
78     private SystemSettingSwitchPreference mEnabledPref;
79     private CMSystemSettingSwitchPreference mCustomEnabledPref;
80     private CMSystemSettingSwitchPreference mMultipleLedsEnabledPref;
81     private CMSystemSettingSwitchPreference mScreenOnLightsPref;
82     private CMSystemSettingSwitchPreference mAutoGenerateColors;
83     private ApplicationLightPreference mDefaultPref;
84     private ApplicationLightPreference mCallPref;
85     private ApplicationLightPreference mVoicemailPref;
86     private Menu mMenu;
87     private PackageListAdapter mPackageAdapter;
88     private String mPackageList;
89     private Map<String, Package> mPackages;
90     private boolean mMultiColorLed;
91
92     @Override
93     public void onCreate(Bundle savedInstanceState) {
94         super.onCreate(savedInstanceState);
95         addPreferencesFromResource(R.xml.notification_light_settings);
96
97         PreferenceScreen prefSet = getPreferenceScreen();
98         Resources resources = getResources();
99
100         PreferenceGroup mAdvancedPrefs = (PreferenceGroup) prefSet.findPreference("advanced_section");
101
102         // Get the system defined default notification color
103         mDefaultColor =
104                 resources.getColor(com.android.internal.R.color.config_defaultNotificationColor, null);
105
106         mDefaultLedOn = resources.getInteger(
107                 com.android.internal.R.integer.config_defaultNotificationLedOn);
108         mDefaultLedOff = resources.getInteger(
109                 com.android.internal.R.integer.config_defaultNotificationLedOff);
110
111         mEnabledPref = (SystemSettingSwitchPreference)
112                 findPreference(Settings.System.NOTIFICATION_LIGHT_PULSE);
113         mEnabledPref.setOnPreferenceChangeListener(this);
114
115         mDefaultPref = (ApplicationLightPreference) findPreference(DEFAULT_PREF);
116         mDefaultPref.setOnPreferenceChangeListener(this);
117
118         mAutoGenerateColors = (CMSystemSettingSwitchPreference)
119                 findPreference(CMSettings.System.NOTIFICATION_LIGHT_COLOR_AUTO);
120
121         // Advanced light settings
122         mNotificationLedBrightnessPref = (PreferenceScreen)
123                 findPreference(CMSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL);
124         mMultipleLedsEnabledPref = (CMSystemSettingSwitchPreference)
125                 findPreference(CMSettings.System.NOTIFICATION_LIGHT_MULTIPLE_LEDS_ENABLE);
126         mScreenOnLightsPref = (CMSystemSettingSwitchPreference)
127                 findPreference(CMSettings.System.NOTIFICATION_LIGHT_SCREEN_ON);
128         mScreenOnLightsPref.setOnPreferenceChangeListener(this);
129         mCustomEnabledPref = (CMSystemSettingSwitchPreference)
130                 findPreference(CMSettings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE);
131         mCustomEnabledPref.setOnPreferenceChangeListener(this);
132         if (!resources.getBoolean(
133                 org.cyanogenmod.platform.internal.R.bool.config_adjustableNotificationLedBrightness)) {
134             mAdvancedPrefs.removePreference(mNotificationLedBrightnessPref);
135         } else {
136             mNotificationLedBrightnessPref.setOnPreferenceChangeListener(this);
137         }
138         if (!resources.getBoolean(
139                 org.cyanogenmod.platform.internal.R.bool.config_multipleNotificationLeds)) {
140             mAdvancedPrefs.removePreference(mMultipleLedsEnabledPref);
141         } else {
142             mMultipleLedsEnabledPref.setOnPreferenceChangeListener(this);
143         }
144
145         // Missed call and Voicemail preferences should only show on devices with a voice capabilities
146         TelephonyManager tm = (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
147         if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) {
148             removePreference("phone_list");
149         } else {
150             mCallPref = (ApplicationLightPreference) findPreference(MISSED_CALL_PREF);
151             mCallPref.setOnPreferenceChangeListener(this);
152
153             mVoicemailPref = (ApplicationLightPreference) findPreference(VOICEMAIL_PREF);
154             mVoicemailPref.setOnPreferenceChangeListener(this);
155         }
156
157         mApplicationPrefList = (PreferenceGroup) findPreference("applications_list");
158         mApplicationPrefList.setOrderingAsAdded(false);
159
160         // Get launch-able applications
161         mPackageManager = getPackageManager();
162         mPackageAdapter = new PackageListAdapter(getActivity());
163
164         mPackages = new HashMap<String, Package>();
165         setHasOptionsMenu(true);
166
167         mMultiColorLed = resources.getBoolean(com.android.internal.R.bool.config_multiColorNotificationLed);
168         if (!mMultiColorLed) {
169             resetColors();
170             PreferenceGroup mGeneralPrefs = (PreferenceGroup) prefSet.findPreference("general_section");
171             mGeneralPrefs.removePreference(mAutoGenerateColors);
172         } else {
173             mAutoGenerateColors.setOnPreferenceChangeListener(this);
174         }
175     }
176
177     @Override
178     protected int getMetricsCategory() {
179         return CMMetricsLogger.NOTIFICATION_LIGHT_SETTINGS;
180     }
181
182     @Override
183     public void onResume() {
184         super.onResume();
185         refreshDefault();
186         refreshCustomApplicationPrefs();
187         getListView().setOnItemLongClickListener(this);
188         getActivity().invalidateOptionsMenu();
189     }
190
191     @Override
192     public void onStart() {
193         super.onStart();
194         setChildrenStarted(getPreferenceScreen(), true);
195     }
196
197     @Override
198     public void onStop() {
199         super.onStop();
200         setChildrenStarted(getPreferenceScreen(), false);
201     }
202
203     private void setChildrenStarted(PreferenceGroup group, boolean started) {
204         final int count = group.getPreferenceCount();
205         for (int i = 0; i < count; i++) {
206             Preference pref = group.getPreference(i);
207             if (pref instanceof ApplicationLightPreference) {
208                 ApplicationLightPreference ap = (ApplicationLightPreference) pref;
209                 if (started) {
210                     ap.onStart();
211                 } else {
212                     ap.onStop();
213                 }
214             } else if (pref instanceof PreferenceGroup) {
215                 setChildrenStarted((PreferenceGroup) pref, started);
216             }
217         }
218     }
219
220     private void refreshDefault() {
221         ContentResolver resolver = getContentResolver();
222         int color = CMSettings.System.getInt(resolver,
223                 CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR, mDefaultColor);
224         int timeOn = CMSettings.System.getInt(resolver,
225                 CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON, mDefaultLedOn);
226         int timeOff = CMSettings.System.getInt(resolver,
227                 CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF, mDefaultLedOff);
228
229         mDefaultPref.setAllValues(color, timeOn, timeOff);
230
231         // Get Missed call and Voicemail values
232         if (mCallPref != null) {
233             int callColor = CMSettings.System.getInt(resolver,
234                     CMSettings.System.NOTIFICATION_LIGHT_PULSE_CALL_COLOR, mDefaultColor);
235             int callTimeOn = CMSettings.System.getInt(resolver,
236                     CMSettings.System.NOTIFICATION_LIGHT_PULSE_CALL_LED_ON, mDefaultLedOn);
237             int callTimeOff = CMSettings.System.getInt(resolver,
238                     CMSettings.System.NOTIFICATION_LIGHT_PULSE_CALL_LED_OFF, mDefaultLedOff);
239
240             mCallPref.setAllValues(callColor, callTimeOn, callTimeOff);
241         }
242
243         if (mVoicemailPref != null) {
244             int vmailColor = CMSettings.System.getInt(resolver,
245                     CMSettings.System.NOTIFICATION_LIGHT_PULSE_VMAIL_COLOR, mDefaultColor);
246             int vmailTimeOn = CMSettings.System.getInt(resolver,
247                     CMSettings.System.NOTIFICATION_LIGHT_PULSE_VMAIL_LED_ON, mDefaultLedOn);
248             int vmailTimeOff = CMSettings.System.getInt(resolver,
249                     CMSettings.System.NOTIFICATION_LIGHT_PULSE_VMAIL_LED_OFF, mDefaultLedOff);
250
251             mVoicemailPref.setAllValues(vmailColor, vmailTimeOn, vmailTimeOff);
252         }
253
254         mApplicationPrefList = (PreferenceGroup) findPreference("applications_list");
255         mApplicationPrefList.setOrderingAsAdded(false);
256     }
257
258     private void refreshCustomApplicationPrefs() {
259         Context context = getActivity();
260
261         if (!parsePackageList()) {
262             return;
263         }
264
265         // Add the Application Preferences
266         if (mApplicationPrefList != null) {
267             mApplicationPrefList.removeAll();
268
269             for (Package pkg : mPackages.values()) {
270                 try {
271                     PackageInfo info = mPackageManager.getPackageInfo(pkg.name,
272                             PackageManager.GET_META_DATA);
273                     ApplicationLightPreference pref =
274                             new ApplicationLightPreference(context, pkg.color, pkg.timeon, pkg.timeoff);
275
276                     pref.setKey(pkg.name);
277                     pref.setTitle(info.applicationInfo.loadLabel(mPackageManager));
278                     pref.setIcon(info.applicationInfo.loadIcon(mPackageManager));
279                     pref.setPersistent(false);
280                     pref.setOnPreferenceChangeListener(this);
281
282                     mApplicationPrefList.addPreference(pref);
283                 } catch (NameNotFoundException e) {
284                     // Do nothing
285                 }
286             }
287         }
288     }
289
290     private int getInitialColorForPackage(String packageName) {
291         boolean autoColor = CMSettings.System.getInt(getContentResolver(),
292                 CMSettings.System.NOTIFICATION_LIGHT_COLOR_AUTO, mMultiColorLed ? 1 : 0) == 1;
293         int color = mDefaultColor;
294         if (autoColor) {
295             try {
296                 Drawable icon = mPackageManager.getApplicationIcon(packageName);
297                 color = ColorUtils.generateAlertColorFromDrawable(icon);
298             } catch (NameNotFoundException e) {
299                 // shouldn't happen, but just return default
300             }
301         }
302         return color;
303     }
304
305     private void addCustomApplicationPref(String packageName) {
306         Package pkg = mPackages.get(packageName);
307         if (pkg == null) {
308             int color = getInitialColorForPackage(packageName);
309             pkg = new Package(packageName, color, mDefaultLedOn, mDefaultLedOff);
310             mPackages.put(packageName, pkg);
311             savePackageList(false);
312             refreshCustomApplicationPrefs();
313         }
314     }
315
316     private void removeCustomApplicationPref(String packageName) {
317         if (mPackages.remove(packageName) != null) {
318             savePackageList(false);
319             refreshCustomApplicationPrefs();
320         }
321     }
322
323     private boolean parsePackageList() {
324         final String baseString = CMSettings.System.getString(getContentResolver(),
325                 CMSettings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES);
326
327         if (TextUtils.equals(mPackageList, baseString)) {
328             return false;
329         }
330
331         mPackageList = baseString;
332         mPackages.clear();
333
334         if (baseString != null) {
335             final String[] array = TextUtils.split(baseString, "\\|");
336             for (String item : array) {
337                 if (TextUtils.isEmpty(item)) {
338                     continue;
339                 }
340                 Package pkg = Package.fromString(item);
341                 if (pkg != null) {
342                     mPackages.put(pkg.name, pkg);
343                 }
344             }
345         }
346
347         return true;
348     }
349
350     private void savePackageList(boolean preferencesUpdated) {
351         List<String> settings = new ArrayList<String>();
352         for (Package app : mPackages.values()) {
353             settings.add(app.toString());
354         }
355         final String value = TextUtils.join("|", settings);
356         if (preferencesUpdated) {
357             mPackageList = value;
358         }
359         CMSettings.System.putString(getContentResolver(),
360                                   CMSettings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES, value);
361     }
362
363     /**
364      * Updates the default or package specific notification settings.
365      *
366      * @param packageName Package name of application specific settings to update
367      * @param color
368      * @param timeon
369      * @param timeoff
370      */
371     protected void updateValues(String packageName, Integer color, Integer timeon, Integer timeoff) {
372         ContentResolver resolver = getContentResolver();
373
374         if (packageName.equals(DEFAULT_PREF)) {
375             CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR, color);
376             CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON, timeon);
377             CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF, timeoff);
378             refreshDefault();
379             return;
380         } else if (packageName.equals(MISSED_CALL_PREF)) {
381             CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_CALL_COLOR, color);
382             CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_CALL_LED_ON, timeon);
383             CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_CALL_LED_OFF, timeoff);
384             refreshDefault();
385             return;
386         } else if (packageName.equals(VOICEMAIL_PREF)) {
387             CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_VMAIL_COLOR, color);
388             CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_VMAIL_LED_ON, timeon);
389             CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_VMAIL_LED_OFF, timeoff);
390             refreshDefault();
391             return;
392         }
393
394         // Find the custom package and sets its new values
395         Package app = mPackages.get(packageName);
396         if (app != null) {
397             app.color = color;
398             app.timeon = timeon;
399             app.timeoff = timeoff;
400             savePackageList(true);
401         }
402     }
403
404     protected void resetColors() {
405         ContentResolver resolver = getContentResolver();
406
407         // Reset to the framework default colors
408         CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR, mDefaultColor);
409         CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_CALL_COLOR, mDefaultColor);
410         CMSettings.System.putInt(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_VMAIL_COLOR, mDefaultColor);
411
412         refreshDefault();
413     }
414
415     public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
416         final Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem(position);
417
418         if (mApplicationPrefList.findPreference(pref.getKey()) != pref) {
419             return false;
420         }
421
422         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
423                 .setTitle(R.string.dialog_delete_title)
424                 .setMessage(R.string.dialog_delete_message)
425                 .setIconAttribute(android.R.attr.alertDialogIcon)
426                 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
427                     @Override
428                     public void onClick(DialogInterface dialog, int which) {
429                         removeCustomApplicationPref(pref.getKey());
430                     }
431                 })
432                 .setNegativeButton(android.R.string.cancel, null);
433
434         builder.show();
435         return true;
436     }
437
438     public boolean onPreferenceChange(Preference preference, Object objValue) {
439         if (preference == mEnabledPref || preference == mCustomEnabledPref ||
440                 preference == mMultipleLedsEnabledPref ||
441                 preference == mNotificationLedBrightnessPref ||
442                 preference == mScreenOnLightsPref ||
443                 preference == mAutoGenerateColors) {
444             getActivity().invalidateOptionsMenu();
445         } else {
446             ApplicationLightPreference lightPref = (ApplicationLightPreference) preference;
447             updateValues(lightPref.getKey(), lightPref.getColor(),
448                     lightPref.getOnValue(), lightPref.getOffValue());
449         }
450
451         return true;
452     }
453
454     @Override
455     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
456         mMenu = menu;
457         mMenu.add(0, MENU_ADD, 0, R.string.profiles_add)
458                 .setIcon(R.drawable.ic_menu_add_white)
459                 .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
460     }
461
462     @Override
463     public void onPrepareOptionsMenu(Menu menu) {
464         boolean enableAddButton = mEnabledPref.isChecked() && mCustomEnabledPref.isChecked();
465         menu.findItem(MENU_ADD).setVisible(enableAddButton);
466     }
467
468     @Override
469     public boolean onOptionsItemSelected(MenuItem item) {
470         switch (item.getItemId()) {
471             case MENU_ADD:
472                 showDialog(DIALOG_APPS);
473                 return true;
474         }
475         return false;
476     }
477
478     /**
479      * Utility classes and supporting methods
480      */
481     @Override
482     public Dialog onCreateDialog(int id) {
483         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
484         final Dialog dialog;
485         switch (id) {
486             case DIALOG_APPS:
487                 final ListView list = new ListView(getActivity());
488                 list.setAdapter(mPackageAdapter);
489
490                 builder.setTitle(R.string.profile_choose_app);
491                 builder.setView(list);
492                 dialog = builder.create();
493
494                 list.setOnItemClickListener(new OnItemClickListener() {
495                     @Override
496                     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
497                         // Add empty application definition, the user will be able to edit it later
498                         PackageItem info = (PackageItem) parent.getItemAtPosition(position);
499                         addCustomApplicationPref(info.packageName);
500                         dialog.cancel();
501                     }
502                 });
503                 break;
504             default:
505                 dialog = null;
506         }
507         return dialog;
508     }
509
510     /**
511      * Application class
512      */
513     private static class Package {
514         public String name;
515         public Integer color;
516         public Integer timeon;
517         public Integer timeoff;
518
519         /**
520          * Stores all the application values in one call
521          * @param name
522          * @param color
523          * @param timeon
524          * @param timeoff
525          */
526         public Package(String name, Integer color, Integer timeon, Integer timeoff) {
527             this.name = name;
528             this.color = color;
529             this.timeon = timeon;
530             this.timeoff = timeoff;
531         }
532
533         public String toString() {
534             StringBuilder builder = new StringBuilder();
535             builder.append(name);
536             builder.append("=");
537             builder.append(color);
538             builder.append(";");
539             builder.append(timeon);
540             builder.append(";");
541             builder.append(timeoff);
542             return builder.toString();
543         }
544
545         public static Package fromString(String value) {
546             if (TextUtils.isEmpty(value)) {
547                 return null;
548             }
549             String[] app = value.split("=", -1);
550             if (app.length != 2)
551                 return null;
552
553             String[] values = app[1].split(";", -1);
554             if (values.length != 3)
555                 return null;
556
557             try {
558                 Package item = new Package(app[0], Integer.parseInt(values[0]), Integer
559                         .parseInt(values[1]), Integer.parseInt(values[2]));
560                 return item;
561             } catch (NumberFormatException e) {
562                 return null;
563             }
564         }
565
566     }
567 }