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