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
17package com.android.deskclock;
18
19import android.app.Activity;
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.BatteryManager;
27import android.os.Handler;
28import android.provider.Settings;
29import android.util.Log;
30import android.view.View;
31import android.view.Window;
32import android.view.WindowManager;
33import android.widget.TextClock;
34
35import com.android.deskclock.Utils.ScreensaverMoveSaverRunnable;
36
37public class ScreensaverActivity extends Activity {
38    static final boolean DEBUG = false;
39    static final String TAG = "DeskClock/ScreensaverActivity";
40
41    // This value must match android:defaultValue of
42    // android:key="screensaver_clock_style" in dream_settings.xml
43    static final String DEFAULT_CLOCK_STYLE = "digital";
44
45    private View mContentView, mSaverView;
46    private View mAnalogClock, mDigitalClock;
47
48    private final Handler mHandler = new Handler();
49    private final ScreensaverMoveSaverRunnable mMoveSaverRunnable;
50    private String mDateFormat;
51    private String mDateFormatForAccessibility;
52    private String mClockStyle;
53    private boolean mPluggedIn = true;
54    private final int mFlags = (WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
55            | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
56            | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
57            | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
58
59    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
60        @Override
61        public void onReceive(Context context, Intent intent) {
62            boolean changed = intent.getAction().equals(Intent.ACTION_TIME_CHANGED)
63                    || intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED);
64            if (intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)) {
65                mPluggedIn = true;
66                setWakeLock();
67            } else if (intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)) {
68                mPluggedIn = false;
69                setWakeLock();
70            } else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
71                finish();
72            }
73
74            if (changed) {
75                Utils.updateDate(mDateFormat, mDateFormatForAccessibility, mContentView);
76                Utils.refreshAlarm(ScreensaverActivity.this, mContentView);
77                Utils.setMidnightUpdater(mHandler, mMidnightUpdater);
78            }
79
80        }
81    };
82
83    private final ContentObserver mSettingsContentObserver = new ContentObserver(mHandler) {
84        @Override
85        public void onChange(boolean selfChange) {
86            Utils.refreshAlarm(ScreensaverActivity.this, mContentView);
87        }
88    };
89
90    // Thread that runs every midnight and refreshes the date.
91    private final Runnable mMidnightUpdater = new Runnable() {
92        @Override
93        public void run() {
94            Utils.updateDate(mDateFormat, mDateFormatForAccessibility, mContentView);
95            Utils.setMidnightUpdater(mHandler, mMidnightUpdater);
96        }
97    };
98
99    public ScreensaverActivity() {
100        if (DEBUG) Log.d(TAG, "Screensaver allocated");
101        mMoveSaverRunnable = new ScreensaverMoveSaverRunnable(mHandler);
102    }
103
104    @Override
105    public void onStart() {
106        super.onStart();
107        IntentFilter filter = new IntentFilter();
108        filter.addAction(Intent.ACTION_POWER_CONNECTED);
109        filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
110        filter.addAction(Intent.ACTION_USER_PRESENT);
111        filter.addAction(Intent.ACTION_TIME_CHANGED);
112        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
113        registerReceiver(mIntentReceiver, filter);
114        getContentResolver().registerContentObserver(
115                Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED),
116                false,
117                mSettingsContentObserver);
118    }
119
120    @Override
121    public void onResume() {
122        super.onResume();
123        Intent chargingIntent =
124                registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
125        int plugged = chargingIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
126        mPluggedIn = plugged == BatteryManager.BATTERY_PLUGGED_AC
127                || plugged == BatteryManager.BATTERY_PLUGGED_USB
128                || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
129
130        mDateFormat = getString(R.string.abbrev_wday_month_day_no_year);
131        mDateFormatForAccessibility = getString(R.string.full_wday_month_day_no_year);
132
133        setWakeLock();
134        layoutClockSaver();
135        mHandler.post(mMoveSaverRunnable);
136
137        Utils.setMidnightUpdater(mHandler, mMidnightUpdater);
138    }
139
140    @Override
141    public void onPause() {
142        mHandler.removeCallbacks(mMoveSaverRunnable);
143        Utils.cancelMidnightUpdater(mHandler, mMidnightUpdater);
144        finish();
145        super.onPause();
146    }
147
148    @Override
149    public void onStop() {
150        getContentResolver().unregisterContentObserver(mSettingsContentObserver);
151        unregisterReceiver(mIntentReceiver);
152        super.onStop();
153   }
154
155    @Override
156    public void onConfigurationChanged(Configuration newConfig) {
157        if (DEBUG) Log.d(TAG, "Screensaver configuration changed");
158        super.onConfigurationChanged(newConfig);
159        mHandler.removeCallbacks(mMoveSaverRunnable);
160        layoutClockSaver();
161        mHandler.postDelayed(mMoveSaverRunnable, 250);
162    }
163
164    @Override
165    public void onUserInteraction() {
166        // We want the screen saver to exit upon user interaction.
167        finish();
168    }
169
170    private void setWakeLock() {
171        Window win = getWindow();
172        WindowManager.LayoutParams winParams = win.getAttributes();
173        winParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
174        if (mPluggedIn)
175            winParams.flags |= mFlags;
176        else
177            winParams.flags &= (~mFlags);
178        win.setAttributes(winParams);
179    }
180
181    private void setClockStyle() {
182        Utils.setClockStyle(this, mDigitalClock, mAnalogClock,
183                SettingsActivity.KEY_CLOCK_STYLE);
184        mSaverView = findViewById(R.id.main_clock);
185        mClockStyle = (mSaverView == mDigitalClock ?
186                Utils.CLOCK_TYPE_DIGITAL : Utils.CLOCK_TYPE_ANALOG);
187        Utils.dimClockView(true, mSaverView);
188    }
189
190    private void layoutClockSaver() {
191        setContentView(R.layout.desk_clock_saver);
192        mDigitalClock = findViewById(R.id.digital_clock);
193        mAnalogClock = findViewById(R.id.analog_clock);
194        setClockStyle();
195        Utils.setTimeFormat((TextClock)mDigitalClock,
196            (int)getResources().getDimension(R.dimen.bottom_text_size));
197
198        mContentView = (View) mSaverView.getParent();
199        mContentView.forceLayout();
200        mSaverView.forceLayout();
201        mSaverView.setAlpha(0);
202
203        mMoveSaverRunnable.registerViews(mContentView, mSaverView);
204
205        mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
206                | View.SYSTEM_UI_FLAG_FULLSCREEN
207                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
208
209        Utils.updateDate(mDateFormat, mDateFormatForAccessibility,mContentView);
210        Utils.refreshAlarm(ScreensaverActivity.this, mContentView);
211    }
212
213}
214