/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.deskclock;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.animation.TimeInterpolator;
import android.animation.ObjectAnimator;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.app.Activity;
import android.os.BatteryManager;
import android.os.Handler;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.TextView;
import java.lang.Runnable;
import android.util.Log;
public class Screensaver extends Activity {
static final boolean DEBUG = false;
static final String TAG = "DeskClock/Screensaver";
static int CLOCK_COLOR = 0xFF66AAFF;
static final long MOVE_DELAY = 60000; // DeskClock.SCREEN_SAVER_MOVE_DELAY;
static final long SLIDE_TIME = 10000;
static final long FADE_TIME = 1000;
static final boolean SLIDE = false;
private View mContentView, mSaverView;
private static TimeInterpolator mSlowStartWithBrakes =
new TimeInterpolator() {
public float getInterpolation(float x) {
return (float)(Math.cos((Math.pow(x,3) + 1) * Math.PI) / 2.0f) + 0.5f;
}
};
private Handler mHandler = new Handler();
private boolean mPlugged = false;
private final BroadcastReceiver mPowerIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
// Only keep the screen on if we're plugged in.
boolean plugged = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
if (plugged != mPlugged) {
if (DEBUG) Log.v(TAG, plugged ? "plugged in" : "unplugged");
mPlugged = plugged;
if (mPlugged) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
}
}
}
};
private final Runnable mMoveSaverRunnable = new Runnable() {
@Override
public void run() {
long delay = MOVE_DELAY;
// Log.d("DeskClock/Screensaver",
// String.format("mContentView=(%d x %d) container=(%d x %d)",
// mContentView.getWidth(), mContentView.getHeight(),
// mSaverView.getWidth(), mSaverView.getHeight()
// ));
final float xrange = mContentView.getWidth() - mSaverView.getWidth();
final float yrange = mContentView.getHeight() - mSaverView.getHeight();
if (xrange == 0 && yrange == 0) {
delay = 500; // back in a split second
} else {
final int nextx = (int) (Math.random() * xrange);
final int nexty = (int) (Math.random() * yrange);
if (mSaverView.getAlpha() == 0f) {
// jump right there
mSaverView.setX(nextx);
mSaverView.setY(nexty);
ObjectAnimator.ofFloat(mSaverView, "alpha", 0f, 1f)
.setDuration(FADE_TIME)
.start();
} else {
AnimatorSet s = new AnimatorSet();
Animator xMove = ObjectAnimator.ofFloat(mSaverView,
"x", mSaverView.getX(), nextx);
Animator yMove = ObjectAnimator.ofFloat(mSaverView,
"y", mSaverView.getY(), nexty);
Animator xShrink = ObjectAnimator.ofFloat(mSaverView, "scaleX", 1f, 0.85f);
Animator xGrow = ObjectAnimator.ofFloat(mSaverView, "scaleX", 0.85f, 1f);
Animator yShrink = ObjectAnimator.ofFloat(mSaverView, "scaleY", 1f, 0.85f);
Animator yGrow = ObjectAnimator.ofFloat(mSaverView, "scaleY", 0.85f, 1f);
AnimatorSet shrink = new AnimatorSet(); shrink.play(xShrink).with(yShrink);
AnimatorSet grow = new AnimatorSet(); grow.play(xGrow).with(yGrow);
Animator fadeout = ObjectAnimator.ofFloat(mSaverView, "alpha", 1f, 0f);
Animator fadein = ObjectAnimator.ofFloat(mSaverView, "alpha", 0f, 1f);
if (SLIDE) {
s.play(xMove).with(yMove);
s.setDuration(SLIDE_TIME);
s.play(shrink.setDuration(SLIDE_TIME/2));
s.play(grow.setDuration(SLIDE_TIME/2)).after(shrink);
s.setInterpolator(mSlowStartWithBrakes);
} else {
AccelerateInterpolator accel = new AccelerateInterpolator();
DecelerateInterpolator decel = new DecelerateInterpolator();
shrink.setDuration(FADE_TIME).setInterpolator(accel);
fadeout.setDuration(FADE_TIME).setInterpolator(accel);
grow.setDuration(FADE_TIME).setInterpolator(decel);
fadein.setDuration(FADE_TIME).setInterpolator(decel);
s.play(shrink);
s.play(fadeout);
s.play(xMove.setDuration(0)).after(FADE_TIME);
s.play(yMove.setDuration(0)).after(FADE_TIME);
s.play(fadein).after(FADE_TIME);
s.play(grow).after(FADE_TIME);
}
s.start();
}
long now = System.currentTimeMillis();
long adjust = (now % 60000);
delay = delay
+ (MOVE_DELAY - adjust) // minute aligned
- (SLIDE ? 0 : FADE_TIME) // start moving before the fade
;
if (DEBUG) Log.d(TAG,
"will move again in " + delay + " now=" + now + " adjusted by " + adjust);
}
mHandler.removeCallbacks(this);
mHandler.postDelayed(this, delay);
}
};
@Override
public void onStart() {
super.onStart();
CLOCK_COLOR = getResources().getColor(R.color.screen_saver_color);
setContentView(R.layout.desk_clock_saver);
mSaverView = findViewById(R.id.saver_view);
mContentView = (View) mSaverView.getParent();
mSaverView.setAlpha(0);
AndroidClockTextView timeDisplay = (AndroidClockTextView) findViewById(R.id.timeDisplay);
if (timeDisplay != null) {
timeDisplay.setTextColor(CLOCK_COLOR);
AndroidClockTextView amPm = (AndroidClockTextView)findViewById(R.id.am_pm);
if (amPm != null) amPm.setTextColor(CLOCK_COLOR);
}
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(mPowerIntentReceiver, filter);
}
@Override
public void onAttachedToWindow() {
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
);
mSaverView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
}
@Override
public void onStop() {
unregisterReceiver(mPowerIntentReceiver);
super.onStop();
}
@Override
public void onResume() {
super.onResume();
mHandler.post(mMoveSaverRunnable);
}
@Override
public void onPause() {
super.onPause();
mHandler.removeCallbacks(mMoveSaverRunnable);
}
@Override
public void onUserInteraction() {
finish();
}
}