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