1/*
2 * Copyright (C) 2011 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.deskclock;
18
19import android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.content.res.Configuration;
24import android.database.ContentObserver;
25import android.os.Handler;
26import android.preference.PreferenceManager;
27import android.provider.Settings;
28import android.service.dreams.DreamService;
29import android.util.Log;
30import android.view.View;
31import android.widget.TextClock;
32
33import com.android.deskclock.Utils.ScreensaverMoveSaverRunnable;
34
35public class Screensaver extends DreamService {
36    static final boolean DEBUG = false;
37    static final String TAG = "DeskClock/Screensaver";
38
39    private View mContentView, mSaverView;
40    private View mAnalogClock, mDigitalClock;
41    private String mDateFormat;
42    private String mDateFormatForAccessibility;
43
44    private final Handler mHandler = new Handler();
45
46    private final ScreensaverMoveSaverRunnable mMoveSaverRunnable;
47
48    private final ContentObserver mSettingsContentObserver = new ContentObserver(mHandler) {
49        @Override
50        public void onChange(boolean selfChange) {
51            Utils.refreshAlarm(Screensaver.this, mContentView);
52        }
53    };
54
55    // Thread that runs every midnight and refreshes the date.
56    private final Runnable mMidnightUpdater = new Runnable() {
57        @Override
58        public void run() {
59            Utils.updateDate(mDateFormat, mDateFormatForAccessibility, mContentView);
60            Utils.setMidnightUpdater(mHandler, mMidnightUpdater);
61        }
62    };
63
64    /**
65     * Receiver to handle time reference changes.
66     */
67    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
68        @Override
69        public void onReceive(Context context, Intent intent) {
70            final String action = intent.getAction();
71            if (action != null && (action.equals(Intent.ACTION_TIME_CHANGED)
72                    || action.equals(Intent.ACTION_TIMEZONE_CHANGED))) {
73                Utils.updateDate(mDateFormat, mDateFormatForAccessibility, mContentView);
74                Utils.refreshAlarm(Screensaver.this, mContentView);
75                Utils.setMidnightUpdater(mHandler, mMidnightUpdater);
76            }
77        }
78    };
79
80    public Screensaver() {
81        if (DEBUG) Log.d(TAG, "Screensaver allocated");
82        mMoveSaverRunnable = new ScreensaverMoveSaverRunnable(mHandler);
83    }
84
85    @Override
86    public void onCreate() {
87        if (DEBUG) Log.d(TAG, "Screensaver created");
88        super.onCreate();
89
90        mDateFormat = getString(R.string.abbrev_wday_month_day_no_year);
91        mDateFormatForAccessibility = getString(R.string.full_wday_month_day_no_year);
92    }
93
94    @Override
95    public void onConfigurationChanged(Configuration newConfig) {
96        if (DEBUG) Log.d(TAG, "Screensaver configuration changed");
97        super.onConfigurationChanged(newConfig);
98        mHandler.removeCallbacks(mMoveSaverRunnable);
99        layoutClockSaver();
100        mHandler.post(mMoveSaverRunnable);
101    }
102
103    @Override
104    public void onAttachedToWindow() {
105        if (DEBUG) Log.d(TAG, "Screensaver attached to window");
106        super.onAttachedToWindow();
107
108        // We want the screen saver to exit upon user interaction.
109        setInteractive(false);
110
111        setFullscreen(true);
112
113        layoutClockSaver();
114
115        // Setup handlers for time reference changes and date updates.
116        IntentFilter filter = new IntentFilter();
117        filter.addAction(Intent.ACTION_TIME_CHANGED);
118        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
119        registerReceiver(mIntentReceiver, filter);
120        Utils.setMidnightUpdater(mHandler, mMidnightUpdater);
121
122        getContentResolver().registerContentObserver(
123                Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED),
124                false,
125                mSettingsContentObserver);
126        mHandler.post(mMoveSaverRunnable);
127    }
128
129    @Override
130    public void onDetachedFromWindow() {
131        if (DEBUG) Log.d(TAG, "Screensaver detached from window");
132        super.onDetachedFromWindow();
133
134        mHandler.removeCallbacks(mMoveSaverRunnable);
135        getContentResolver().unregisterContentObserver(mSettingsContentObserver);
136
137        // Tear down handlers for time reference changes and date updates.
138        Utils.cancelMidnightUpdater(mHandler, mMidnightUpdater);
139        unregisterReceiver(mIntentReceiver);
140    }
141
142    private void setClockStyle() {
143        Utils.setClockStyle(this, mDigitalClock, mAnalogClock,
144                ScreensaverSettingsActivity.KEY_CLOCK_STYLE);
145        mSaverView = findViewById(R.id.main_clock);
146        boolean dimNightMode = PreferenceManager.getDefaultSharedPreferences(this)
147                .getBoolean(ScreensaverSettingsActivity.KEY_NIGHT_MODE, false);
148        Utils.dimClockView(dimNightMode, mSaverView);
149        setScreenBright(!dimNightMode);
150    }
151
152    private void layoutClockSaver() {
153        setContentView(R.layout.desk_clock_saver);
154        mDigitalClock = findViewById(R.id.digital_clock);
155        mAnalogClock =findViewById(R.id.analog_clock);
156        setClockStyle();
157        Utils.setTimeFormat((TextClock)mDigitalClock,
158            (int)getResources().getDimension(R.dimen.bottom_text_size));
159
160        mContentView = (View) mSaverView.getParent();
161        mSaverView.setAlpha(0);
162
163        mMoveSaverRunnable.registerViews(mContentView, mSaverView);
164
165        Utils.updateDate(mDateFormat, mDateFormatForAccessibility, mContentView);
166        Utils.refreshAlarm(Screensaver.this, mContentView);
167    }
168}
169