1c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler/*
2c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler * Copyright (C) 2011 The Android Open Source Project
3c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler *
4c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler * Licensed under the Apache License, Version 2.0 (the "License");
5c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler * you may not use this file except in compliance with the License.
6c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler * You may obtain a copy of the License at
7c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler *
8c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler *      http://www.apache.org/licenses/LICENSE-2.0
9c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler *
10c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler * Unless required by applicable law or agreed to in writing, software
11c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler * distributed under the License is distributed on an "AS IS" BASIS,
12c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler * See the License for the specific language governing permissions and
14c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler * limitations under the License.
15c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler */
16c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler
17c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandlerpackage com.android.deskclock;
18c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler
19c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roosimport android.app.AlarmManager;
20ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albertimport android.content.BroadcastReceiver;
21ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albertimport android.content.Context;
22ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albertimport android.content.Intent;
23ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albertimport android.content.IntentFilter;
2490dc136d444ba29fe8db6b20872022b18f18dc94John Spurlockimport android.content.res.Configuration;
2590dc136d444ba29fe8db6b20872022b18f18dc94John Spurlockimport android.os.Handler;
264560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelsonimport android.preference.PreferenceManager;
2717b4ca405a8b0d154f4d8354ab62044cd25b2204Daniel Sandlerimport android.service.dreams.DreamService;
2890dc136d444ba29fe8db6b20872022b18f18dc94John Spurlockimport android.util.Log;
29c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandlerimport android.view.View;
303a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelsonimport android.widget.TextClock;
31c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler
3278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport com.android.deskclock.Utils.ScreensaverMoveSaverRunnable;
3378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
3417b4ca405a8b0d154f4d8354ab62044cd25b2204Daniel Sandlerpublic class Screensaver extends DreamService {
35e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler    static final boolean DEBUG = false;
36e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler    static final String TAG = "DeskClock/Screensaver";
37c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler
38e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler    private View mContentView, mSaverView;
394560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelson    private View mAnalogClock, mDigitalClock;
40c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson    private String mDateFormat;
41c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson    private String mDateFormatForAccessibility;
42e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler
439df9aff951dce59b327f56f5821386a7b40798bdIsaac Katzenelson    private final Handler mHandler = new Handler();
44c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler
4578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    private final ScreensaverMoveSaverRunnable mMoveSaverRunnable;
464560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelson
47eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    // Thread that runs every midnight and refreshes the date.
48eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    private final Runnable mMidnightUpdater = new Runnable() {
49eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        @Override
50eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        public void run() {
51eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas            Utils.updateDate(mDateFormat, mDateFormatForAccessibility, mContentView);
52eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas            Utils.setMidnightUpdater(mHandler, mMidnightUpdater);
53eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        }
54eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    };
55eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas
56eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    /**
57eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas     * Receiver to handle time reference changes.
58eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas     */
59eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
60eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        @Override
61eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        public void onReceive(Context context, Intent intent) {
62eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas            final String action = intent.getAction();
63c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos            if (DEBUG) Log.v(TAG, "Screensaver onReceive, action: " + action);
64c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos
65c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos            if (action == null) {
66c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos                return;
67c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos            }
68c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos
69c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos            if (action.equals(Intent.ACTION_TIME_CHANGED)
70c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos                    || action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
71eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas                Utils.updateDate(mDateFormat, mDateFormatForAccessibility, mContentView);
72eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas                Utils.refreshAlarm(Screensaver.this, mContentView);
73eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas                Utils.setMidnightUpdater(mHandler, mMidnightUpdater);
74c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos            } else if (action.equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) {
75c0743272ad924bc97d335d695be3e6b32a83dd7dAdrian Roos                Utils.refreshAlarm(Screensaver.this, mContentView);
76eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas            }
77eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        }
78eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    };
79eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas
8090dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    public Screensaver() {
8190dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        if (DEBUG) Log.d(TAG, "Screensaver allocated");
8278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        mMoveSaverRunnable = new ScreensaverMoveSaverRunnable(mHandler);
8390dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    }
844560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelson
8590dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    @Override
8690dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    public void onCreate() {
8790dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        if (DEBUG) Log.d(TAG, "Screensaver created");
8890dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        super.onCreate();
89c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson
90441f22cdc93ebc56470f0da86b225caf2a26ebdcBudi Kusmiantoro        setTheme(R.style.DeskClockParentTheme);
91441f22cdc93ebc56470f0da86b225caf2a26ebdcBudi Kusmiantoro
92c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson        mDateFormat = getString(R.string.abbrev_wday_month_day_no_year);
93c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson        mDateFormatForAccessibility = getString(R.string.full_wday_month_day_no_year);
949a1fd04f15b653a6600629aee41c7d3fd7d843b3Daniel Sandler    }
959a1fd04f15b653a6600629aee41c7d3fd7d843b3Daniel Sandler
96e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler    @Override
9790dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    public void onConfigurationChanged(Configuration newConfig) {
9890dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        if (DEBUG) Log.d(TAG, "Screensaver configuration changed");
9990dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        super.onConfigurationChanged(newConfig);
10090dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        mHandler.removeCallbacks(mMoveSaverRunnable);
10190dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        layoutClockSaver();
10290dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        mHandler.post(mMoveSaverRunnable);
103e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler    }
104e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler
105e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler    @Override
10690dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    public void onAttachedToWindow() {
10790dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        if (DEBUG) Log.d(TAG, "Screensaver attached to window");
10890dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        super.onAttachedToWindow();
109c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler
11057ca681913fa5b9cd86a7342a91cfe4cc5b910dfDaniel Sandler        // We want the screen saver to exit upon user interaction.
11157ca681913fa5b9cd86a7342a91cfe4cc5b910dfDaniel Sandler        setInteractive(false);
11257ca681913fa5b9cd86a7342a91cfe4cc5b910dfDaniel Sandler
1133d6adf080cb4a1469244e393807f6921b9f1149bJohn Spurlock        setFullscreen(true);
1141a7820902f3a6428f0bb586f8f1b5a2824838cb0Daniel Sandler
1159a1fd04f15b653a6600629aee41c7d3fd7d843b3Daniel Sandler        layoutClockSaver();
1169a1fd04f15b653a6600629aee41c7d3fd7d843b3Daniel Sandler
117eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        // Setup handlers for time reference changes and date updates.
118eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        IntentFilter filter = new IntentFilter();
119eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        filter.addAction(Intent.ACTION_TIME_CHANGED);
120eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
121eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        registerReceiver(mIntentReceiver, filter);
122eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        Utils.setMidnightUpdater(mHandler, mMidnightUpdater);
123eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas
1240d4404c04475a66c9bcbda6960bd94597985b785Daniel Sandler        mHandler.post(mMoveSaverRunnable);
125c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler    }
126c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler
127c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler    @Override
12890dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    public void onDetachedFromWindow() {
12990dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        if (DEBUG) Log.d(TAG, "Screensaver detached from window");
13090dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        super.onDetachedFromWindow();
13190dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock
132c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler        mHandler.removeCallbacks(mMoveSaverRunnable);
133eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas
134eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        // Tear down handlers for time reference changes and date updates.
1353bb9d29c12584480f3651ccbef86f2777c0b7818Robyn Coultas        Utils.cancelMidnightUpdater(mHandler, mMidnightUpdater);
136eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        unregisterReceiver(mIntentReceiver);
137c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler    }
138c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler
1394560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelson    private void setClockStyle() {
140b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson        Utils.setClockStyle(this, mDigitalClock, mAnalogClock,
14178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                ScreensaverSettingsActivity.KEY_CLOCK_STYLE);
142b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson        mSaverView = findViewById(R.id.main_clock);
14378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        boolean dimNightMode = PreferenceManager.getDefaultSharedPreferences(this)
14478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                .getBoolean(ScreensaverSettingsActivity.KEY_NIGHT_MODE, false);
14578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        Utils.dimClockView(dimNightMode, mSaverView);
14678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        setScreenBright(!dimNightMode);
1478f873a2bca1277f37cc8d08655d73385e5508232Daniel Sandler    }
1489a1fd04f15b653a6600629aee41c7d3fd7d843b3Daniel Sandler
14990dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    private void layoutClockSaver() {
15090dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        setContentView(R.layout.desk_clock_saver);
151b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson        mDigitalClock = findViewById(R.id.digital_clock);
152b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson        mAnalogClock =findViewById(R.id.analog_clock);
1534560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelson        setClockStyle();
1543a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson        Utils.setTimeFormat((TextClock)mDigitalClock,
155577479b809bfd4bf46c014501fa7e47e61275064Budi Kusmiantoro            (int)getResources().getDimension(R.dimen.main_ampm_font_size));
1563a4ba0db218b830af3dd17fde2952125a2e50fdcIsaac Katzenelson
15790dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        mContentView = (View) mSaverView.getParent();
15890dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        mSaverView.setAlpha(0);
15978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
16078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        mMoveSaverRunnable.registerViews(mContentView, mSaverView);
161c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson
162eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        Utils.updateDate(mDateFormat, mDateFormatForAccessibility, mContentView);
163c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson        Utils.refreshAlarm(Screensaver.this, mContentView);
16490dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    }
165c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler}
166