Screensaver.java revision e269bd8658721a71fd9d42084b280042c5258945
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.view.animation.AccelerateInterpolator;
20import android.view.animation.DecelerateInterpolator;
21import android.animation.TimeInterpolator;
22import android.animation.ObjectAnimator;
23import android.animation.Animator;
24import android.animation.AnimatorSet;
25import android.app.Activity;
26import android.os.BatteryManager;
27import android.os.Handler;
28import android.content.BroadcastReceiver;
29import android.content.Context;
30import android.content.Intent;
31import android.content.IntentFilter;
32import android.util.AttributeSet;
33import android.view.View;
34import android.view.ViewGroup;
35import android.view.WindowManager;
36import android.widget.FrameLayout;
37import android.widget.TextView;
38import java.lang.Runnable;
39import android.util.Log;
40
41public class Screensaver extends Activity {
42    static final boolean DEBUG = false;
43    static final String TAG = "DeskClock/Screensaver";
44
45    static int CLOCK_COLOR = 0xFF66AAFF;
46
47    static final long MOVE_DELAY = 60000; // DeskClock.SCREEN_SAVER_MOVE_DELAY;
48    static final long SLIDE_TIME = 10000;
49    static final long FADE_TIME = 1000;
50
51    static final boolean SLIDE = false;
52
53    private View mContentView, mSaverView;
54
55    private static TimeInterpolator mSlowStartWithBrakes =
56        new TimeInterpolator() {
57            public float getInterpolation(float x) {
58                return (float)(Math.cos((Math.pow(x,3) + 1) * Math.PI) / 2.0f) + 0.5f;
59            }
60        };
61
62    private Handler mHandler = new Handler();
63
64    private boolean mPlugged = false;
65    private final BroadcastReceiver mPowerIntentReceiver = new BroadcastReceiver() {
66        @Override
67        public void onReceive(Context context, Intent intent) {
68            final String action = intent.getAction();
69            if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
70                // Only keep the screen on if we're plugged in.
71                boolean plugged = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
72                if (plugged != mPlugged) {
73                    if (DEBUG) Log.v(TAG, plugged ? "plugged in" : "unplugged");
74                    mPlugged = plugged;
75                    if (mPlugged) {
76                        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
77                    } else {
78                        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
79                    }
80                }
81            }
82        }
83    };
84
85    private final Runnable mMoveSaverRunnable = new Runnable() {
86        @Override
87        public void run() {
88            long delay = MOVE_DELAY;
89
90//            Log.d("DeskClock/Screensaver",
91//                    String.format("mContentView=(%d x %d) container=(%d x %d)",
92//                        mContentView.getWidth(), mContentView.getHeight(),
93//                        mSaverView.getWidth(), mSaverView.getHeight()
94//                        ));
95            final float xrange = mContentView.getWidth() - mSaverView.getWidth();
96            final float yrange = mContentView.getHeight() - mSaverView.getHeight();
97
98            if (xrange == 0 && yrange == 0) {
99                delay = 500; // back in a split second
100            } else {
101                final int nextx = (int) (Math.random() * xrange);
102                final int nexty = (int) (Math.random() * yrange);
103
104                if (mSaverView.getAlpha() == 0f) {
105                    // jump right there
106                    mSaverView.setX(nextx);
107                    mSaverView.setY(nexty);
108                    ObjectAnimator.ofFloat(mSaverView, "alpha", 0f, 1f)
109                        .setDuration(FADE_TIME)
110                        .start();
111                } else {
112                    AnimatorSet s = new AnimatorSet();
113                    Animator xMove   = ObjectAnimator.ofFloat(mSaverView,
114                                         "x", mSaverView.getX(), nextx);
115                    Animator yMove   = ObjectAnimator.ofFloat(mSaverView,
116                                         "y", mSaverView.getY(), nexty);
117
118                    Animator xShrink = ObjectAnimator.ofFloat(mSaverView, "scaleX", 1f, 0.85f);
119                    Animator xGrow   = ObjectAnimator.ofFloat(mSaverView, "scaleX", 0.85f, 1f);
120
121                    Animator yShrink = ObjectAnimator.ofFloat(mSaverView, "scaleY", 1f, 0.85f);
122                    Animator yGrow   = ObjectAnimator.ofFloat(mSaverView, "scaleY", 0.85f, 1f);
123                    AnimatorSet shrink = new AnimatorSet(); shrink.play(xShrink).with(yShrink);
124                    AnimatorSet grow = new AnimatorSet(); grow.play(xGrow).with(yGrow);
125
126                    Animator fadeout = ObjectAnimator.ofFloat(mSaverView, "alpha", 1f, 0f);
127                    Animator fadein = ObjectAnimator.ofFloat(mSaverView, "alpha", 0f, 1f);
128
129
130                    if (SLIDE) {
131                        s.play(xMove).with(yMove);
132                        s.setDuration(SLIDE_TIME);
133
134                        s.play(shrink.setDuration(SLIDE_TIME/2));
135                        s.play(grow.setDuration(SLIDE_TIME/2)).after(shrink);
136                        s.setInterpolator(mSlowStartWithBrakes);
137                    } else {
138                        AccelerateInterpolator accel = new AccelerateInterpolator();
139                        DecelerateInterpolator decel = new DecelerateInterpolator();
140
141                        shrink.setDuration(FADE_TIME).setInterpolator(accel);
142                        fadeout.setDuration(FADE_TIME).setInterpolator(accel);
143                        grow.setDuration(FADE_TIME).setInterpolator(decel);
144                        fadein.setDuration(FADE_TIME).setInterpolator(decel);
145                        s.play(shrink);
146                        s.play(fadeout);
147                        s.play(xMove.setDuration(0)).after(FADE_TIME);
148                        s.play(yMove.setDuration(0)).after(FADE_TIME);
149                        s.play(fadein).after(FADE_TIME);
150                        s.play(grow).after(FADE_TIME);
151                    }
152                    s.start();
153                }
154
155                long now = System.currentTimeMillis();
156                long adjust = (now % 60000);
157                delay = delay
158                        + (MOVE_DELAY - adjust) // minute aligned
159                        - (SLIDE ? 0 : FADE_TIME) // start moving before the fade
160                        ;
161                if (DEBUG) Log.d(TAG,
162                        "will move again in " + delay + " now=" + now + " adjusted by " + adjust);
163            }
164
165            mHandler.removeCallbacks(this);
166            mHandler.postDelayed(this, delay);
167        }
168    };
169
170    @Override
171    public void onStart() {
172        super.onStart();
173        CLOCK_COLOR = getResources().getColor(R.color.screen_saver_color);
174        setContentView(R.layout.desk_clock_saver);
175        mSaverView = findViewById(R.id.saver_view);
176        mContentView = (View) mSaverView.getParent();
177        mSaverView.setAlpha(0);
178
179        AndroidClockTextView timeDisplay = (AndroidClockTextView) findViewById(R.id.timeDisplay);
180        if (timeDisplay != null) {
181            timeDisplay.setTextColor(CLOCK_COLOR);
182            AndroidClockTextView amPm = (AndroidClockTextView)findViewById(R.id.am_pm);
183            if (amPm != null) amPm.setTextColor(CLOCK_COLOR);
184        }
185
186        final IntentFilter filter = new IntentFilter();
187        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
188        registerReceiver(mPowerIntentReceiver, filter);
189    }
190
191    @Override
192    public void onAttachedToWindow() {
193        getWindow().addFlags(
194                WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
195              | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
196              );
197        mSaverView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
198    }
199
200
201    @Override
202    public void onStop() {
203        unregisterReceiver(mPowerIntentReceiver);
204        super.onStop();
205    }
206
207    @Override
208    public void onResume() {
209        super.onResume();
210        mHandler.post(mMoveSaverRunnable);
211    }
212
213    @Override
214    public void onPause() {
215        super.onPause();
216        mHandler.removeCallbacks(mMoveSaverRunnable);
217    }
218
219    @Override
220    public void onUserInteraction() {
221        finish();
222    }
223}
224