1 /*
2  * Copyright (C) 2012 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 android.app.Activity;
20 import android.app.AlertDialog;
21 import android.app.Dialog;
22 import android.content.BroadcastReceiver;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.os.Bundle;
28 import android.support.v7.preference.Preference;
29 import android.support.v7.preference.PreferenceViewHolder;
30 import android.util.Log;
31 import android.view.Menu;
32 import android.view.MenuInflater;
33 import android.view.MenuItem;
34 import android.view.MenuItem.OnMenuItemClickListener;
35 import android.view.MotionEvent;
36 import android.view.View;
37 import android.view.View.OnClickListener;
38 import android.view.View.OnTouchListener;
39 import android.widget.ImageView;
40 import android.widget.RadioButton;
41 import android.widget.Switch;
42 import android.widget.TextView;
43 
44 import com.android.internal.logging.MetricsProto.MetricsEvent;
45 import com.android.settings.widget.SwitchBar;
46 import com.android.settingslib.dream.DreamBackend;
47 import com.android.settingslib.dream.DreamBackend.DreamInfo;
48 
49 import java.util.List;
50 
51 public class DreamSettings extends SettingsPreferenceFragment implements
52         SwitchBar.OnSwitchChangeListener {
53     private static final String TAG = DreamSettings.class.getSimpleName();
54     static final boolean DEBUG = false;
55     private static final int DIALOG_WHEN_TO_DREAM = 1;
56     private static final String PACKAGE_SCHEME = "package";
57 
58     private final PackageReceiver mPackageReceiver = new PackageReceiver();
59 
60     private Context mContext;
61     private DreamBackend mBackend;
62     private SwitchBar mSwitchBar;
63     private MenuItem[] mMenuItemsWhenEnabled;
64     private boolean mRefreshing;
65 
66     @Override
getHelpResource()67     public int getHelpResource() {
68         return R.string.help_url_dreams;
69     }
70 
71     @Override
onAttach(Activity activity)72     public void onAttach(Activity activity) {
73         logd("onAttach(%s)", activity.getClass().getSimpleName());
74         super.onAttach(activity);
75         mContext = activity;
76     }
77 
78     @Override
getMetricsCategory()79     protected int getMetricsCategory() {
80         return MetricsEvent.DREAM;
81     }
82 
83     @Override
onCreate(Bundle icicle)84     public void onCreate(Bundle icicle) {
85         logd("onCreate(%s)", icicle);
86         super.onCreate(icicle);
87 
88         mBackend = new DreamBackend(getActivity());
89 
90         setHasOptionsMenu(true);
91     }
92 
93     @Override
onSwitchChanged(Switch switchView, boolean isChecked)94     public void onSwitchChanged(Switch switchView, boolean isChecked) {
95         if (!mRefreshing) {
96             mBackend.setEnabled(isChecked);
97             refreshFromBackend();
98         }
99     }
100 
101     @Override
onStart()102     public void onStart() {
103         logd("onStart()");
104         super.onStart();
105     }
106 
107     @Override
onDestroyView()108     public void onDestroyView() {
109         logd("onDestroyView()");
110         super.onDestroyView();
111 
112         mSwitchBar.removeOnSwitchChangeListener(this);
113         mSwitchBar.hide();
114     }
115 
116     @Override
onActivityCreated(Bundle savedInstanceState)117     public void onActivityCreated(Bundle savedInstanceState) {
118         logd("onActivityCreated(%s)", savedInstanceState);
119         super.onActivityCreated(savedInstanceState);
120 
121         TextView emptyView = (TextView) getView().findViewById(android.R.id.empty);
122         emptyView.setText(R.string.screensaver_settings_disabled_prompt);
123         setEmptyView(emptyView);
124 
125         final SettingsActivity sa = (SettingsActivity) getActivity();
126         mSwitchBar = sa.getSwitchBar();
127         mSwitchBar.addOnSwitchChangeListener(this);
128         mSwitchBar.show();
129     }
130 
131     @Override
onCreateOptionsMenu(Menu menu, MenuInflater inflater)132     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
133         logd("onCreateOptionsMenu()");
134 
135         boolean isEnabled = mBackend.isEnabled();
136 
137         // create "start" action
138         MenuItem start = createMenuItem(menu, R.string.screensaver_settings_dream_start,
139                 MenuItem.SHOW_AS_ACTION_NEVER,
140                 isEnabled, new Runnable(){
141                     @Override
142                     public void run() {
143                         mBackend.startDreaming();
144                     }});
145 
146         // create "when to dream" overflow menu item
147         MenuItem whenToDream = createMenuItem(menu,
148                 R.string.screensaver_settings_when_to_dream,
149                 MenuItem.SHOW_AS_ACTION_NEVER,
150                 isEnabled,
151                 new Runnable() {
152                     @Override
153                     public void run() {
154                         showDialog(DIALOG_WHEN_TO_DREAM);
155                     }});
156 
157         // create "help" overflow menu item (make sure it appears last)
158         super.onCreateOptionsMenu(menu, inflater);
159 
160         mMenuItemsWhenEnabled = new MenuItem[] { start, whenToDream };
161     }
162 
createMenuItem(Menu menu, int titleRes, int actionEnum, boolean isEnabled, final Runnable onClick)163     private MenuItem createMenuItem(Menu menu,
164             int titleRes, int actionEnum, boolean isEnabled, final Runnable onClick) {
165         MenuItem item = menu.add(titleRes);
166         item.setShowAsAction(actionEnum);
167         item.setEnabled(isEnabled);
168         item.setOnMenuItemClickListener(new OnMenuItemClickListener() {
169             @Override
170             public boolean onMenuItemClick(MenuItem item) {
171                 onClick.run();
172                 return true;
173             }
174         });
175         return item;
176     }
177 
178     @Override
onCreateDialog(int dialogId)179     public Dialog onCreateDialog(int dialogId) {
180         logd("onCreateDialog(%s)", dialogId);
181         if (dialogId == DIALOG_WHEN_TO_DREAM)
182             return createWhenToDreamDialog();
183         return super.onCreateDialog(dialogId);
184     }
185 
createWhenToDreamDialog()186     private Dialog createWhenToDreamDialog() {
187         final CharSequence[] items = {
188                 mContext.getString(R.string.screensaver_settings_summary_dock),
189                 mContext.getString(R.string.screensaver_settings_summary_sleep),
190                 mContext.getString(R.string.screensaver_settings_summary_either_short)
191         };
192 
193         int initialSelection = mBackend.isActivatedOnDock() && mBackend.isActivatedOnSleep() ? 2
194                 : mBackend.isActivatedOnDock() ? 0
195                 : mBackend.isActivatedOnSleep() ? 1
196                 : -1;
197 
198         return new AlertDialog.Builder(mContext)
199                 .setTitle(R.string.screensaver_settings_when_to_dream)
200                 .setSingleChoiceItems(items, initialSelection, new DialogInterface.OnClickListener() {
201                     public void onClick(DialogInterface dialog, int item) {
202                         mBackend.setActivatedOnDock(item == 0 || item == 2);
203                         mBackend.setActivatedOnSleep(item == 1 || item == 2);
204                         dialog.dismiss();
205                     }
206                 })
207                 .create();
208     }
209 
210     @Override
211     public void onPause() {
212         logd("onPause()");
213         super.onPause();
214 
215         mContext.unregisterReceiver(mPackageReceiver);
216     }
217 
218     @Override
219     public void onResume() {
220         logd("onResume()");
221         super.onResume();
222         refreshFromBackend();
223 
224         // listen for package changes
225         IntentFilter filter = new IntentFilter();
226         filter.addAction(Intent.ACTION_PACKAGE_ADDED);
227         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
228         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
229         filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
230         filter.addDataScheme(PACKAGE_SCHEME);
231         mContext.registerReceiver(mPackageReceiver , filter);
232     }
233 
234     public static int getSummaryResource(Context context) {
235         DreamBackend backend = new DreamBackend(context);
236         boolean isEnabled = backend.isEnabled();
237         boolean activatedOnSleep = backend.isActivatedOnSleep();
238         boolean activatedOnDock = backend.isActivatedOnDock();
239         boolean activatedOnEither = activatedOnSleep && activatedOnDock;
240         return !isEnabled ? R.string.screensaver_settings_summary_off
241                 : activatedOnEither ? R.string.screensaver_settings_summary_either_long
242                 : activatedOnSleep ? R.string.screensaver_settings_summary_sleep
243                 : activatedOnDock ? R.string.screensaver_settings_summary_dock
244                 : 0;
245     }
246 
247     public static CharSequence getSummaryTextWithDreamName(Context context) {
248         DreamBackend backend = new DreamBackend(context);
249         boolean isEnabled = backend.isEnabled();
250         if (!isEnabled) {
251             return context.getString(R.string.screensaver_settings_summary_off);
252         } else {
253             return backend.getActiveDreamName();
254         }
255     }
256 
257     private void refreshFromBackend() {
258         logd("refreshFromBackend()");
259         mRefreshing = true;
260         boolean dreamsEnabled = mBackend.isEnabled();
261         if (mSwitchBar.isChecked() != dreamsEnabled) {
262             mSwitchBar.setChecked(dreamsEnabled);
263         }
264 
265         if (getPreferenceScreen() == null) {
266             setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
267         }
268         getPreferenceScreen().removeAll();
269         if (dreamsEnabled) {
270             List<DreamBackend.DreamInfo> dreamInfos = mBackend.getDreamInfos();
271             final int N = dreamInfos.size();
272             for (int i = 0; i < N; i++) {
273                 getPreferenceScreen().addPreference(
274                         new DreamInfoPreference(getPrefContext(), dreamInfos.get(i)));
275             }
276         }
277         if (mMenuItemsWhenEnabled != null) {
278             for (MenuItem menuItem : mMenuItemsWhenEnabled) {
279                 menuItem.setEnabled(dreamsEnabled);
280             }
281         }
282         mRefreshing = false;
283     }
284 
285     private static void logd(String msg, Object... args) {
286         if (DEBUG) Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));
287     }
288 
289     private class DreamInfoPreference extends Preference {
290 
291         private final DreamInfo mInfo;
292 
293         public DreamInfoPreference(Context context, DreamInfo info) {
294             super(context);
295             mInfo = info;
296             setLayoutResource(R.layout.dream_info_row);
297             setTitle(mInfo.caption);
298             setIcon(mInfo.icon);
299         }
300 
301         public void onBindViewHolder(final PreferenceViewHolder holder) {
302             super.onBindViewHolder(holder);
303 
304             // bind radio button
305             RadioButton radioButton = (RadioButton) holder.findViewById(android.R.id.button1);
306             radioButton.setChecked(mInfo.isActive);
307             radioButton.setOnTouchListener(new OnTouchListener() {
308                 @Override
309                 public boolean onTouch(View v, MotionEvent event) {
310                     holder.itemView.onTouchEvent(event);
311                     return false;
312                 }
313             });
314 
315             // bind settings button + divider
316             boolean showSettings = mInfo.settingsComponentName != null;
317             View settingsDivider = holder.findViewById(R.id.divider);
318             settingsDivider.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE);
319 
320             ImageView settingsButton = (ImageView) holder.findViewById(android.R.id.button2);
321             settingsButton.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE);
322             settingsButton.setAlpha(mInfo.isActive ? 1f : Utils.DISABLED_ALPHA);
323             settingsButton.setEnabled(mInfo.isActive);
324             settingsButton.setFocusable(mInfo.isActive);
325             settingsButton.setOnClickListener(new OnClickListener(){
326                 @Override
327                 public void onClick(View v) {
328                     mBackend.launchSettings(mInfo);
329                 }
330             });
331         }
332 
333         @Override
334         public void performClick() {
335             if (mInfo.isActive)
336                 return;
337             for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
338                 DreamInfoPreference preference =
339                         (DreamInfoPreference) getPreferenceScreen().getPreference(i);
340                 preference.mInfo.isActive = false;
341                 preference.notifyChanged();
342             }
343             mInfo.isActive = true;
344             mBackend.setActiveDream(mInfo.componentName);
345             notifyChanged();
346         }
347     }
348 
349     private class PackageReceiver extends BroadcastReceiver {
350         @Override
351         public void onReceive(Context context, Intent intent) {
352             logd("PackageReceiver.onReceive");
353             refreshFromBackend();
354         }
355     }
356 }
357