1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.systemui.tuner;
16 
17 
18 import android.app.AlertDialog;
19 import android.app.Dialog;
20 import android.app.DialogFragment;
21 import android.content.DialogInterface;
22 import android.os.Bundle;
23 import android.provider.Settings;
24 import android.provider.Settings.Secure;
25 import android.support.v14.preference.PreferenceFragment;
26 import android.support.v7.preference.Preference;
27 import android.view.LayoutInflater;
28 import android.view.View;
29 import android.widget.SeekBar;
30 
31 import com.android.internal.logging.MetricsLogger;
32 import com.android.internal.logging.MetricsProto.MetricsEvent;
33 import com.android.systemui.R;
34 import com.android.systemui.statusbar.policy.NightModeController;
35 
36 public class ColorAndAppearanceFragment extends PreferenceFragment {
37 
38     private static final String KEY_CALIBRATE = "calibrate";
39 
40     private static final long RESET_DELAY = 10000;
41     private static final CharSequence KEY_NIGHT_MODE = "night_mode";
42 
43     private NightModeController mNightModeController;
44 
45     @Override
onCreate(Bundle savedInstanceState)46     public void onCreate(Bundle savedInstanceState) {
47         super.onCreate(savedInstanceState);
48         mNightModeController = new NightModeController(getContext());
49     }
50 
51     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)52     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
53         addPreferencesFromResource(R.xml.color_and_appearance);
54     }
55 
56     @Override
onResume()57     public void onResume() {
58         super.onResume();
59         MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_COLOR_AND_APPEARANCE, true);
60         // TODO: Figure out better title model for Tuner, to avoid any more of this.
61         getActivity().setTitle(R.string.color_and_appearance);
62 
63         Preference nightMode = findPreference(KEY_NIGHT_MODE);
64         nightMode.setSummary(mNightModeController.isEnabled()
65                 ? R.string.night_mode_on : R.string.night_mode_off);
66     }
67 
68     @Override
onPause()69     public void onPause() {
70         super.onPause();
71         MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_COLOR_AND_APPEARANCE, false);
72     }
73 
74     @Override
onDisplayPreferenceDialog(Preference preference)75     public void onDisplayPreferenceDialog(Preference preference) {
76         if (preference instanceof CalibratePreference) {
77             CalibrateDialog.show(this);
78         } else {
79             super.onDisplayPreferenceDialog(preference);
80         }
81     }
82 
startRevertTimer()83     private void startRevertTimer() {
84         getView().postDelayed(mResetColorMatrix, RESET_DELAY);
85     }
86 
onApply()87     private void onApply() {
88         MetricsLogger.action(getContext(), MetricsEvent.ACTION_TUNER_CALIBRATE_DISPLAY_CHANGED);
89         mNightModeController.setCustomValues(Settings.Secure.getString(
90                 getContext().getContentResolver(), Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX));
91         getView().removeCallbacks(mResetColorMatrix);
92     }
93 
onRevert()94     private void onRevert() {
95         getView().removeCallbacks(mResetColorMatrix);
96         mResetColorMatrix.run();
97     }
98 
99     private final Runnable mResetColorMatrix = new Runnable() {
100         @Override
101         public void run() {
102             ((DialogFragment) getFragmentManager().findFragmentByTag("RevertWarning")).dismiss();
103             Settings.Secure.putString(getContext().getContentResolver(),
104                     Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
105         }
106     };
107 
108     public static class CalibrateDialog extends DialogFragment implements
109             DialogInterface.OnClickListener {
110         private float[] mValues;
111         private NightModeController mNightModeController;
112 
show(ColorAndAppearanceFragment fragment)113         public static void show(ColorAndAppearanceFragment fragment) {
114             CalibrateDialog dialog = new CalibrateDialog();
115             dialog.setTargetFragment(fragment, 0);
116             dialog.show(fragment.getFragmentManager(), "Calibrate");
117         }
118 
119         @Override
onCreate(Bundle savedInstanceState)120         public void onCreate(Bundle savedInstanceState) {
121             super.onCreate(savedInstanceState);
122             mNightModeController = new NightModeController(getContext());
123             String customValues = mNightModeController.getCustomValues();
124             if (customValues == null) {
125                 // Generate this as a string because its the easiest way to generate a copy of the
126                 // identity.
127                 customValues = NightModeController.toString(NightModeController.IDENTITY_MATRIX);
128             }
129             mValues = NightModeController.toValues(customValues);
130         }
131 
132         @Override
onCreateDialog(Bundle savedInstanceState)133         public Dialog onCreateDialog(Bundle savedInstanceState) {
134             View v = LayoutInflater.from(getContext()).inflate(R.layout.calibrate_sliders, null);
135             bindView(v.findViewById(R.id.r_group), 0);
136             bindView(v.findViewById(R.id.g_group), 5);
137             bindView(v.findViewById(R.id.b_group), 10);
138             MetricsLogger.visible(getContext(), MetricsEvent.TUNER_CALIBRATE_DISPLAY);
139             return new AlertDialog.Builder(getContext())
140                     .setTitle(R.string.calibrate_display)
141                     .setView(v)
142                     .setPositiveButton(R.string.color_apply, this)
143                     .setNegativeButton(android.R.string.cancel, null)
144                     .create();
145         }
146 
147         @Override
onDismiss(DialogInterface dialog)148         public void onDismiss(DialogInterface dialog) {
149             super.onDismiss(dialog);
150             MetricsLogger.hidden(getContext(), MetricsEvent.TUNER_CALIBRATE_DISPLAY);
151         }
152 
bindView(View view, final int index)153         private void bindView(View view, final int index) {
154             SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
155             seekBar.setMax(1000);
156             seekBar.setProgress((int) (1000 * mValues[index]));
157             seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
158                 @Override
159                 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
160                     mValues[index] = progress / 1000f;
161                 }
162 
163                 @Override
164                 public void onStartTrackingTouch(SeekBar seekBar) {
165                 }
166 
167                 @Override
168                 public void onStopTrackingTouch(SeekBar seekBar) {
169                 }
170             });
171         }
172 
173         @Override
onClick(DialogInterface dialog, int which)174         public void onClick(DialogInterface dialog, int which) {
175             if (mValues[0] == 1 && mValues[5] == 1 && mValues[10] == 1) {
176                 // Allow removal of matrix by all values set to highest.
177                 mNightModeController.setCustomValues(null);
178                 return;
179             }
180             ((ColorAndAppearanceFragment) getTargetFragment()).startRevertTimer();
181             Settings.Secure.putString(getContext().getContentResolver(),
182                     Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
183                     NightModeController.toString(mValues));
184             RevertWarning.show((ColorAndAppearanceFragment) getTargetFragment());
185         }
186     }
187 
188     public static class RevertWarning extends DialogFragment
189             implements DialogInterface.OnClickListener {
190 
show(ColorAndAppearanceFragment fragment)191         public static void show(ColorAndAppearanceFragment fragment) {
192             RevertWarning warning = new RevertWarning();
193             warning.setTargetFragment(fragment, 0);
194             warning.show(fragment.getFragmentManager(), "RevertWarning");
195         }
196 
197         @Override
onCreateDialog(Bundle savedInstanceState)198         public Dialog onCreateDialog(Bundle savedInstanceState) {
199             AlertDialog alertDialog = new AlertDialog.Builder(getContext())
200                     .setTitle(R.string.color_revert_title)
201                     .setMessage(R.string.color_revert_message)
202                     .setPositiveButton(R.string.ok, this)
203                     .create();
204             alertDialog.setCanceledOnTouchOutside(true);
205             return alertDialog;
206         }
207 
208         @Override
onCancel(DialogInterface dialog)209         public void onCancel(DialogInterface dialog) {
210             super.onCancel(dialog);
211             ((ColorAndAppearanceFragment) getTargetFragment()).onRevert();
212         }
213 
214         @Override
onClick(DialogInterface dialog, int which)215         public void onClick(DialogInterface dialog, int which) {
216             ((ColorAndAppearanceFragment) getTargetFragment()).onApply();
217         }
218     }
219 }
220