summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Sandler <dsandler@android.com>2012-04-10 05:33:07 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-04-10 05:33:07 -0700
commitc38cf4c7dbe7d96255d42dabf8ca801830813f5e (patch)
treec34bc1561f67c0838d7ebd4d625b568738dc4589
parent06cce885296f60b6cc2d0dad3d167681536a53a5 (diff)
parent7d276c377ce0c56630c06a6da431a6cb9bd76d1e (diff)
downloadframeworks_base-c38cf4c7dbe7d96255d42dabf8ca801830813f5e.zip
frameworks_base-c38cf4c7dbe7d96255d42dabf8ca801830813f5e.tar.gz
frameworks_base-c38cf4c7dbe7d96255d42dabf8ca801830813f5e.tar.bz2
Merge "New Android Dreams architecture, disabled for now."
-rw-r--r--Android.mk2
-rw-r--r--core/java/android/service/dreams/Dream.java392
-rw-r--r--core/java/android/service/dreams/DreamManagerService.java182
-rw-r--r--core/java/android/service/dreams/IDreamManager.aidl30
-rw-r--r--core/java/android/service/dreams/IDreamService.aidl24
-rw-r--r--core/java/android/view/WindowManager.java6
-rw-r--r--core/java/android/view/WindowManagerPolicy.java25
-rw-r--r--core/res/res/anim/slow_fade_in.xml24
-rwxr-xr-xcore/res/res/values/config.xml2
-rw-r--r--core/res/res/values/public.xml4
-rw-r--r--core/res/res/values/styles.xml6
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java149
-rw-r--r--services/java/com/android/server/PowerManagerService.java15
-rw-r--r--services/java/com/android/server/SystemServer.java20
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java12
15 files changed, 808 insertions, 85 deletions
diff --git a/Android.mk b/Android.mk
index 9c51fc6..cacdee9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -132,6 +132,8 @@ LOCAL_SRC_FILES += \
core/java/android/os/IRemoteCallback.aidl \
core/java/android/os/IUpdateLock.aidl \
core/java/android/os/IVibratorService.aidl \
+ core/java/android/service/dreams/IDreamManager.aidl \
+ core/java/android/service/dreams/IDreamService.aidl \
core/java/android/service/wallpaper/IWallpaperConnection.aidl \
core/java/android/service/wallpaper/IWallpaperEngine.aidl \
core/java/android/service/wallpaper/IWallpaperService.aidl \
diff --git a/core/java/android/service/dreams/Dream.java b/core/java/android/service/dreams/Dream.java
new file mode 100644
index 0000000..83464c9
--- /dev/null
+++ b/core/java/android/service/dreams/Dream.java
@@ -0,0 +1,392 @@
+/**
+ *
+ */
+package android.service.dreams;
+
+import com.android.internal.policy.PolicyManager;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.view.ActionMode;
+import android.view.IWindowManager;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.WindowManager;
+import android.view.WindowManagerImpl;
+
+/**
+ * @hide
+ *
+ */
+public class Dream extends Service implements Window.Callback {
+ private final static boolean DEBUG = true;
+ private final static String TAG = "Dream";
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ * To be supported, the service must also require the
+ * {@link android.Manifest.permission#BIND_WALLPAPER} permission so
+ * that other applications can not abuse it.
+ */
+ @SdkConstant(SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE =
+ "android.service.dreams.Dream";
+
+ private Window mWindow;
+
+ private WindowManager mWindowManager;
+ private IDreamManager mSandman;
+
+ private boolean mInteractive;
+
+ final Handler mHandler = new Handler();
+
+ boolean mFinished = false;
+
+ // begin Window.Callback methods
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (!mInteractive) {
+ finish();
+ return true;
+ }
+ return mWindow.superDispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+ if (!mInteractive) {
+ finish();
+ return true;
+ }
+ return mWindow.superDispatchKeyShortcutEvent(event);
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ if (!mInteractive) {
+ finish();
+ return true;
+ }
+ return mWindow.superDispatchTouchEvent(event);
+ }
+
+ @Override
+ public boolean dispatchTrackballEvent(MotionEvent event) {
+ if (!mInteractive) {
+ finish();
+ return true;
+ }
+ return mWindow.superDispatchTrackballEvent(event);
+ }
+
+ @Override
+ public boolean dispatchGenericMotionEvent(MotionEvent event) {
+ if (!mInteractive) {
+ finish();
+ return true;
+ }
+ return mWindow.superDispatchGenericMotionEvent(event);
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ return false;
+ }
+
+ @Override
+ public View onCreatePanelView(int featureId) {
+ return null;
+ }
+
+ @Override
+ public boolean onCreatePanelMenu(int featureId, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onPreparePanel(int featureId, View view, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onMenuOpened(int featureId, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {
+ return false;
+ }
+
+ @Override
+ public void onWindowAttributesChanged(LayoutParams attrs) {
+
+ }
+
+ @Override
+ public void onContentChanged() {
+
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ mWindow.addFlags(
+ WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
+ | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+ );
+ lightsOut();
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ }
+
+ @Override
+ public void onPanelClosed(int featureId, Menu menu) {
+ }
+
+ @Override
+ public boolean onSearchRequested() {
+ return false;
+ }
+
+ @Override
+ public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) {
+ return null;
+ }
+
+ @Override
+ public void onActionModeStarted(ActionMode mode) {
+ }
+
+ @Override
+ public void onActionModeFinished(ActionMode mode) {
+ }
+ // end Window.Callback methods
+
+ public WindowManager getWindowManager() {
+ return mWindowManager;
+ }
+
+ public Window getWindow() {
+ return mWindow;
+ }
+
+ /**
+ * Called when this Dream is constructed. Place your initialization here.
+ *
+ * Subclasses must call through to the superclass implementation.
+ */
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ if (DEBUG) Slog.v(TAG, "Dream created on thread " + Thread.currentThread().getId());
+
+ mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
+ }
+
+ /**
+ * Called when this Dream is started. Place your initialization here.
+ *
+ * Subclasses must call through to the superclass implementation.
+ *
+ * XXX(dsandler) Might want to make this final and have a different method for clients to override
+ */
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ /**
+ * Inflate a layout resource and set it to be the content view for this Dream.
+ * Behaves similarly to {@link android.app.Activity#setContentView(int)}.
+ *
+ * @param layoutResID Resource ID to be inflated.
+ *
+ * @see #setContentView(android.view.View)
+ * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
+ */
+ public void setContentView(int layoutResID) {
+ getWindow().setContentView(layoutResID);
+ }
+
+ /**
+ * Set a view to be the content view for this Dream.
+ * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)},
+ * including using {@link ViewGroup.LayoutParams#MATCH_PARENT} as the layout height and width of the view.
+ *
+ * @param view The desired content to display.
+ *
+ * @see #setContentView(int)
+ * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
+ */
+ public void setContentView(View view) {
+ getWindow().setContentView(view);
+ }
+
+ /**
+ * Set a view to be the content view for this Dream.
+ * Behaves similarly to
+ * {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}.
+ *
+ * @param view The desired content to display.
+ * @param params Layout parameters for the view.
+ *
+ * @see #setContentView(android.view.View)
+ * @see #setContentView(int)
+ */
+ public void setContentView(View view, ViewGroup.LayoutParams params) {
+ getWindow().setContentView(view, params);
+ }
+
+ /**
+ * Add a view to the Dream's window, leaving other content views in place.
+ *
+ * @param view The desired content to display.
+ * @param params Layout parameters for the view.
+ */
+ public void addContentView(View view, ViewGroup.LayoutParams params) {
+ getWindow().addContentView(view, params);
+ }
+
+ /**
+ * @param mInteractive the mInteractive to set
+ */
+ public void setInteractive(boolean mInteractive) {
+ this.mInteractive = mInteractive;
+ }
+
+ /**
+ * @return the mInteractive
+ */
+ public boolean isInteractive() {
+ return mInteractive;
+ }
+
+ /** Convenience method for setting View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view. */
+ protected void lightsOut() {
+ // turn the lights down low
+ final View v = mWindow.getDecorView();
+ if (v != null) {
+ v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ }
+ }
+
+ /**
+ * Finds a view that was identified by the id attribute from the XML that
+ * was processed in {@link #onCreate}.
+ *
+ * @return The view if found or null otherwise.
+ */
+ public View findViewById(int id) {
+ return getWindow().findViewById(id);
+ }
+
+ /**
+ * Called when this Dream is being removed from the screen and stopped.
+ */
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mWindowManager.removeView(mWindow.getDecorView());
+ }
+
+ /**
+ * Creates a new dream window, attaches the current content view, and shows it.
+ *
+ * @param windowToken Binder to attach to the window to allow access to the correct window type.
+ * @hide
+ */
+ final /*package*/ void attach(IBinder windowToken) {
+ if (DEBUG) Slog.v(TAG, "Dream attached on thread " + Thread.currentThread().getId());
+
+ mWindow = PolicyManager.makeNewWindow(this);
+ mWindow.setCallback(this);
+ mWindow.requestFeature(Window.FEATURE_NO_TITLE);
+ mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
+
+ if (DEBUG) Slog.v(TAG, "attaching window token: " + windowToken
+ + " to window of type " + WindowManager.LayoutParams.TYPE_DREAM);
+
+ WindowManager.LayoutParams lp = mWindow.getAttributes();
+ lp.type = WindowManager.LayoutParams.TYPE_DREAM;
+ lp.token = windowToken;
+ lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
+
+ //WindowManagerImpl.getDefault().addView(mWindow.getDecorView(), lp);
+
+ if (DEBUG) Slog.v(TAG, "created and attached window: " + mWindow);
+
+ mWindow.setWindowManager(null, windowToken, "dream", true);
+ mWindowManager = mWindow.getWindowManager();
+
+ // now make it visible
+ mHandler.post(new Runnable(){
+ @Override
+ public void run() {
+ if (DEBUG) Slog.v(TAG, "Dream window added on thread " + Thread.currentThread().getId());
+
+ getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
+ }});
+ }
+
+ /**
+ * Stop the dream and wake up.
+ *
+ * After this method is called, the service will be stopped.
+ */
+ public void finish() {
+ if (mFinished) return;
+ try {
+ mSandman.awaken(); // assuming we were started by the DreamManager
+ stopSelf(); // if launched via any other means
+ mFinished = true;
+ } catch (RemoteException ex) {
+ // sigh
+ }
+ }
+
+ class IDreamServiceWrapper extends IDreamService.Stub {
+ public IDreamServiceWrapper() {
+ }
+
+ public void attach(IBinder windowToken) {
+ Dream.this.attach(windowToken);
+ }
+ }
+
+ /**
+ * Implement to return the implementation of the internal accessibility
+ * service interface. Subclasses should not override.
+ */
+ @Override
+ public final IBinder onBind(Intent intent) {
+ return new IDreamServiceWrapper();
+ }
+}
diff --git a/core/java/android/service/dreams/DreamManagerService.java b/core/java/android/service/dreams/DreamManagerService.java
new file mode 100644
index 0000000..8712fa2
--- /dev/null
+++ b/core/java/android/service/dreams/DreamManagerService.java
@@ -0,0 +1,182 @@
+package android.service.dreams;
+
+import static android.provider.Settings.Secure.SCREENSAVER_COMPONENT;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import com.android.internal.view.IInputMethod;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.util.Log;
+import android.util.Slog;
+import android.view.IWindowManager;
+import android.view.WindowManager;
+
+/**
+ *
+ * @hide
+ *
+ */
+
+public class DreamManagerService
+ extends IDreamManager.Stub
+ implements ServiceConnection
+{
+ private static final boolean DEBUG = true;
+ private static final String TAG = "DreamManagerService";
+
+ final Object mLock = new Object[0];
+
+ private Context mContext;
+ private IWindowManager mIWindowManager;
+
+ private ComponentName mCurrentDreamComponent;
+ private IDreamService mCurrentDream;
+ private Binder mCurrentDreamToken;
+
+ public DreamManagerService(Context context) {
+ if (DEBUG) Slog.v(TAG, "DreamManagerService startup");
+ mContext = context;
+ mIWindowManager = IWindowManager.Stub.asInterface(
+ ServiceManager.getService(Context.WINDOW_SERVICE));
+ }
+
+ private void checkPermission(String permission) {
+ if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(permission)) {
+ throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
+ + ", must have permission " + permission);
+ }
+ }
+
+ // IDreamManager method
+ public void dream() {
+ ComponentName name = getDreamComponent();
+ if (name != null) {
+ synchronized (mLock) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ bindDreamComponentL(name, false);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+ }
+
+ // IDreamManager method
+ public void setDreamComponent(ComponentName name) {
+ Settings.Secure.putString(mContext.getContentResolver(), SCREENSAVER_COMPONENT, name.flattenToString());
+ }
+
+ // IDreamManager method
+ public ComponentName getDreamComponent() {
+ // TODO(dsandler) don't load this every time, watch the value
+ String component = Settings.Secure.getString(mContext.getContentResolver(), SCREENSAVER_COMPONENT);
+ if (component == null) {
+ component = mContext.getResources().getString(
+ com.android.internal.R.string.config_defaultDreamComponent);
+ }
+ if (component != null) {
+ return ComponentName.unflattenFromString(component);
+ } else {
+ return null;
+ }
+ }
+
+ // IDreamManager method
+ public void testDream(ComponentName name) {
+ if (DEBUG) Slog.v(TAG, "startDream name=" + name
+ + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+// checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
+ synchronized (mLock) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ bindDreamComponentL(name, true);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ // IDreamManager method
+ public void awaken() {
+ if (DEBUG) Slog.v(TAG, "awaken()");
+ synchronized (mLock) {
+ if (mCurrentDream != null) {
+ mContext.unbindService(this);
+ }
+ }
+ }
+
+ public void bindDreamComponentL(ComponentName componentName, boolean test) {
+ if (DEBUG) Slog.v(TAG, "bindDreamComponent: componentName=" + componentName
+ + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+
+ Intent intent = new Intent(Intent.ACTION_MAIN)
+ .setComponent(componentName)
+ .addFlags(
+ Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ )
+ .putExtra("android.dreams.TEST", test);
+
+ if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) {
+ Slog.w(TAG, "unable to bind service: " + componentName);
+ return;
+ }
+ mCurrentDreamComponent = componentName;
+ mCurrentDreamToken = new Binder();
+ try {
+ if (DEBUG) Slog.v(TAG, "Adding window token: " + mCurrentDreamToken
+ + " for window type: " + WindowManager.LayoutParams.TYPE_DREAM);
+ mIWindowManager.addWindowToken(mCurrentDreamToken,
+ WindowManager.LayoutParams.TYPE_DREAM);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Unable to add window token. Proceed at your own risk.");
+ }
+
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) Slog.v(TAG, "connected to dream: " + name + " binder=" + service + " thread=" + Thread.currentThread().getId());
+
+ mCurrentDream = IDreamService.Stub.asInterface(service);
+ try {
+ if (DEBUG) Slog.v(TAG, "attaching with token:" + mCurrentDreamToken);
+ mCurrentDream.attach(mCurrentDreamToken);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Unable to send window token to dream:" + ex);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG) Slog.v(TAG, "disconnected: " + name + " service: " + mCurrentDream);
+ mCurrentDream = null;
+ mCurrentDreamToken = null;
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("Dreamland:");
+ pw.print(" component="); pw.println(mCurrentDreamComponent);
+ pw.print(" token="); pw.println(mCurrentDreamToken);
+ pw.print(" dream="); pw.println(mCurrentDream);
+ }
+
+ public void systemReady() {
+ if (DEBUG) Slog.v(TAG, "ready to dream!");
+ }
+
+}
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
new file mode 100644
index 0000000..7225013
--- /dev/null
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2012, 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 android.service.dreams;
+
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.content.ComponentName;
+
+/** @hide */
+interface IDreamManager {
+ void dream();
+ void awaken();
+ void setDreamComponent(in ComponentName componentName);
+ ComponentName getDreamComponent();
+ void testDream(in ComponentName componentName);
+} \ No newline at end of file
diff --git a/core/java/android/service/dreams/IDreamService.aidl b/core/java/android/service/dreams/IDreamService.aidl
new file mode 100644
index 0000000..1bb241a
--- /dev/null
+++ b/core/java/android/service/dreams/IDreamService.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 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 android.service.dreams;
+
+/**
+ * @hide
+ */
+oneway interface IDreamService {
+ void attach(IBinder windowToken);
+}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index f3ef329..bc310b0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -423,6 +423,12 @@ public interface WindowManager extends ViewManager {
public static final int TYPE_HIDDEN_NAV_CONSUMER = FIRST_SYSTEM_WINDOW+22;
/**
+ * Window type: Dreams (screen saver) window, just above keyguard.
+ * @hide
+ */
+ public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23;
+
+ /**
* End of types of system windows.
*/
public static final int LAST_SYSTEM_WINDOW = 2999;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 491cd67..66bdc5d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1049,6 +1049,31 @@ public interface WindowManagerPolicy {
public void lockNow();
/**
+ * Check to see if a screensaver should be run instead of powering off the screen on timeout.
+ *
+ * @return true if the screensaver should run, false if the screen should turn off.
+ *
+ * @hide
+ */
+ public boolean isScreenSaverEnabled();
+
+ /**
+ * Start the screensaver (if it is enabled and not yet running).
+ *
+ * @return Whether the screensaver was successfully started.
+ *
+ * @hide
+ */
+ public boolean startScreenSaver();
+
+ /**
+ * Stop the screensaver if it is running.
+ *
+ * @hide
+ */
+ public void stopScreenSaver();
+
+ /**
* Print the WindowManagerPolicy's state into the given stream.
*
* @param prefix Text to print at the front of each line.
diff --git a/core/res/res/anim/slow_fade_in.xml b/core/res/res/anim/slow_fade_in.xml
new file mode 100644
index 0000000..21a2c78
--- /dev/null
+++ b/core/res/res/anim/slow_fade_in.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/fade_in.xml
+**
+** Copyright 2012, 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.
+*/
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@interpolator/decelerate_quad"
+ android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:duration="1000" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4fde018..e80e30a 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -837,6 +837,8 @@
<!-- Name of the wimax state tracker clas -->
<string name="config_wimaxStateTrackerClassname" translatable="false"></string>
+ <!-- enable screen saver feature -->
+ <bool name="config_enableDreams">false</bool>
<!-- Name of screensaver components to look for if none has been chosen by the user -->
<string name="config_defaultDreamComponent" translatable="false">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ca0e913..cbfc1a4 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1110,6 +1110,7 @@
<java-symbol type="style" name="Animation.PopupWindow" />
<java-symbol type="style" name="Animation.TypingFilter" />
<java-symbol type="style" name="Animation.TypingFilterRestore" />
+ <java-symbol type="style" name="Animation.Dream" />
<java-symbol type="style" name="Theme.DeviceDefault.Dialog.Alert" />
<java-symbol type="style" name="Theme.DeviceDefault.Light.Dialog.Alert" />
<java-symbol type="style" name="Theme.Dialog.Alert" />
@@ -1262,7 +1263,6 @@
<java-symbol type="layout" name="screen_title_icons" />
<java-symbol type="string" name="abbrev_wday_month_day_no_year" />
<java-symbol type="string" name="android_upgrading_title" />
- <java-symbol type="string" name="config_defaultDreamComponent" />
<java-symbol type="string" name="faceunlock_multiple_failures" />
<java-symbol type="string" name="global_action_power_off" />
<java-symbol type="string" name="global_actions_airplane_mode_off_status" />
@@ -1480,6 +1480,8 @@
<java-symbol type="style" name="Theme.Dialog.AppError" />
<java-symbol type="style" name="Theme.Toast" />
<java-symbol type="xml" name="storage_list" />
+ <java-symbol type="bool" name="config_enableDreams" />
+ <java-symbol type="string" name="config_defaultDreamComponent" />
<!-- From SystemUI -->
<java-symbol type="anim" name="push_down_in" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index bc5b1bc..18ee2f8 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -219,6 +219,12 @@ please see styles_device_defaults.xml.
<item name="windowExitAnimation">@anim/fade_out</item>
</style>
+ <!-- Window animations for screen savers. {@hide} -->
+ <style name="Animation.Dream">
+ <item name="windowEnterAnimation">@anim/slow_fade_in</item>
+ <item name="windowExitAnimation">@anim/fast_fade_out</item>
+ </style>
+
<!-- Status Bar Styles -->
<style name="TextAppearance.StatusBar">
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index f3622ef..d150b5c 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -65,6 +65,7 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.telephony.ITelephony;
import com.android.internal.widget.PointerLocationView;
+import android.service.dreams.IDreamManager;
import android.speech.RecognizerIntent;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -108,6 +109,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
@@ -202,26 +204,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// responsible for power management when displayed.
static final int KEYGUARD_LAYER = 11;
static final int KEYGUARD_DIALOG_LAYER = 12;
- static final int STATUS_BAR_SUB_PANEL_LAYER = 13;
- static final int STATUS_BAR_LAYER = 14;
- static final int STATUS_BAR_PANEL_LAYER = 15;
+ // used for Dreams (screensavers with TYPE_DREAM windows)
+ static final int SCREENSAVER_LAYER = 13;
+ static final int STATUS_BAR_SUB_PANEL_LAYER = 14;
+ static final int STATUS_BAR_LAYER = 15;
+ static final int STATUS_BAR_PANEL_LAYER = 16;
// the on-screen volume indicator and controller shown when the user
// changes the device volume
- static final int VOLUME_OVERLAY_LAYER = 16;
+ static final int VOLUME_OVERLAY_LAYER = 17;
// things in here CAN NOT take focus, but are shown on top of everything else.
- static final int SYSTEM_OVERLAY_LAYER = 17;
+ static final int SYSTEM_OVERLAY_LAYER = 18;
// the navigation bar, if available, shows atop most things
- static final int NAVIGATION_BAR_LAYER = 18;
+ static final int NAVIGATION_BAR_LAYER = 19;
// system-level error dialogs
- static final int SYSTEM_ERROR_LAYER = 19;
+ static final int SYSTEM_ERROR_LAYER = 20;
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
- static final int DRAG_LAYER = 20;
- static final int SECURE_SYSTEM_OVERLAY_LAYER = 21;
- static final int BOOT_PROGRESS_LAYER = 22;
+ static final int DRAG_LAYER = 21;
+ static final int SECURE_SYSTEM_OVERLAY_LAYER = 22;
+ static final int BOOT_PROGRESS_LAYER = 23;
// the (mouse) pointer layer
- static final int POINTER_LAYER = 23;
- static final int HIDDEN_NAV_CONSUMER_LAYER = 24;
+ static final int POINTER_LAYER = 24;
+ static final int HIDDEN_NAV_CONSUMER_LAYER = 25;
static final int APPLICATION_MEDIA_SUBLAYER = -2;
static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -453,6 +457,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mLockScreenTimerActive;
// visual screen saver support
+ boolean mScreenSaverFeatureAvailable;
int mScreenSaverTimeout = 0;
boolean mScreenSaverEnabledByUser = false;
boolean mScreenSaverMayRun = true; // false if a wakelock is held
@@ -1076,6 +1081,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
updateRotation = true;
}
+ // dreams
+ mScreenSaverFeatureAvailable = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableDreams);
+
mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver,
Settings.Secure.SCREENSAVER_ENABLED, 1);
@@ -1091,7 +1100,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mScreenSaverTimeout -= 5000;
}
}
- updateScreenSaverTimeoutLocked();
}
if (updateRotation) {
updateRotation(true);
@@ -1179,6 +1187,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// this... should introduce a token to let the system
// monitor/control what they are doing.
break;
+ case TYPE_DREAM:
case TYPE_INPUT_METHOD:
case TYPE_WALLPAPER:
// The window manager will check these.
@@ -1309,6 +1318,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return BOOT_PROGRESS_LAYER;
case TYPE_HIDDEN_NAV_CONSUMER:
return HIDDEN_NAV_CONSUMER_LAYER;
+ case TYPE_DREAM:
+ return SCREENSAVER_LAYER;
}
Log.e(TAG, "Unknown window type: " + type);
return APPLICATION_LAYER;
@@ -3330,7 +3341,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
synchronized (mLock) {
updateOrientationListenerLp();
updateLockScreenTimeout();
- updateScreenSaverTimeoutLocked();
}
}
@@ -3379,7 +3389,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mScreenOnEarly = true;
updateOrientationListenerLp();
updateLockScreenTimeout();
- updateScreenSaverTimeoutLocked();
}
}
@@ -3769,83 +3778,58 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
}
}
+ }
- synchronized (mLock) {
- // Only posts messages; holds no additional locks.
- updateScreenSaverTimeoutLocked();
+ private IDreamManager getDreamManager() {
+ if (!mScreenSaverFeatureAvailable) {
+ return null;
}
+
+ IDreamManager sandman = IDreamManager.Stub.asInterface(
+ ServiceManager.checkService("dreams"));
+ if (sandman == null) {
+ Log.w(TAG, "Unable to find IDreamManager");
+ }
+ return sandman;
}
- Runnable mScreenSaverActivator = new Runnable() {
- public void run() {
- if (!(mScreenSaverMayRun && mScreenOnEarly)) {
- Log.w(TAG, "mScreenSaverActivator ran, but the screensaver should not be showing. Who's driving this thing?");
- return;
- }
- if (!mPluggedIn) {
- if (localLOGV) Log.v(TAG, "mScreenSaverActivator: not running screen saver when not plugged in");
- return;
- }
- // Quick fix for automation tests.
- // The correct fix is to move this triggering logic to PowerManager, where more complete
- // information about wakelocks (including StayOnWhilePluggedIn) is available.
- if (Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.STAY_ON_WHILE_PLUGGED_IN,
- BatteryManager.BATTERY_PLUGGED_AC) != 0) {
- Log.v(TAG, "mScreenSaverActivator: not running screen saver when STAY_ON_WHILE_PLUGGED_IN");
- return;
- }
+ @Override
+ public boolean isScreenSaverEnabled() {
+ return (mScreenSaverFeatureAvailable && mScreenSaverEnabledByUser
+ && mScreenSaverMayRun && mScreenOnEarly && mPluggedIn);
+ }
- if (localLOGV) Log.v(TAG, "mScreenSaverActivator entering dreamland");
+ @Override
+ public boolean startScreenSaver() {
+ synchronized (mLock) {
+ if (isScreenSaverEnabled()) {
+ IDreamManager dm = getDreamManager();
+ if (dm == null) return false;
+
+ try {
+ if (localLOGV) Log.v(TAG, "startScreenSaver: entering dreamland...");
- try {
- String component = Settings.Secure.getString(
- mContext.getContentResolver(), Settings.Secure.SCREENSAVER_COMPONENT);
- if (component == null) {
- component = mContext.getResources().getString(R.string.config_defaultDreamComponent);
+ dm.dream();
+ return true;
+ } catch (RemoteException ex) {
+ // too bad, so sad, oh mom, oh dad
}
- if (component != null) {
- // dismiss the notification shade, recents, etc.
- mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
- .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT));
-
- ComponentName cn = ComponentName.unflattenFromString(component);
- Intent intent = new Intent(Intent.ACTION_MAIN)
- .setComponent(cn)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_NO_USER_ACTION
- | Intent.FLAG_FROM_BACKGROUND
- | Intent.FLAG_ACTIVITY_NO_HISTORY
- );
- mContext.startActivity(intent);
- } else {
- Log.e(TAG, "Couldn't start screen saver: none selected");
- }
- } catch (android.content.ActivityNotFoundException exc) {
- // no screensaver? give up
- Log.e(TAG, "Couldn't start screen saver: none installed");
}
}
- };
-
- // Must call while holding mLock
- private void updateScreenSaverTimeoutLocked() {
- if (mScreenSaverActivator == null) return;
+ return false;
+ }
- mHandler.removeCallbacks(mScreenSaverActivator);
- if (mScreenSaverEnabledByUser && mScreenSaverMayRun && mScreenOnEarly && mScreenSaverTimeout > 0) {
- if (localLOGV)
- Log.v(TAG, "scheduling screensaver for " + mScreenSaverTimeout + "ms from now");
- mHandler.postDelayed(mScreenSaverActivator, mScreenSaverTimeout);
- } else {
- if (localLOGV) {
- if (!mScreenSaverEnabledByUser || mScreenSaverTimeout == 0)
- Log.v(TAG, "screen saver disabled by user");
- else if (!mScreenOnEarly)
- Log.v(TAG, "screen saver disabled while screen off");
- else
- Log.v(TAG, "screen saver disabled by wakelock");
+ @Override
+ public void stopScreenSaver() {
+ synchronized (mLock) {
+ IDreamManager dm = getDreamManager();
+ if (dm == null) return;
+
+ try {
+ if (localLOGV) Log.v(TAG, "startScreenSaver: awakening...");
+
+ dm.awaken();
+ } catch (RemoteException ex) {
}
}
}
@@ -4091,7 +4075,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// even if the keyguard is up, now that all the wakelocks have been released, we
// should re-enable the screen saver
mScreenSaverMayRun = true;
- updateScreenSaverTimeoutLocked();
}
}
}
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 52a4110..bebce7e 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -1752,7 +1752,7 @@ public class PowerManagerService extends IPowerManager.Stub
+ " noChangeLights=" + noChangeLights
+ " reason=" + reason);
}
-
+
if (noChangeLights) {
newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
}
@@ -1794,6 +1794,19 @@ public class PowerManagerService extends IPowerManager.Stub
final boolean stateChanged = mPowerState != newState;
+ if (stateChanged && reason == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT) {
+ if (mPolicy.isScreenSaverEnabled()) {
+ if (mSpew) {
+ Slog.d(TAG, "setPowerState: running screen saver instead of turning off screen");
+ }
+ if (mPolicy.startScreenSaver()) {
+ // was successful
+ return;
+ }
+ }
+ }
+
+
if (oldScreenOn != newScreenOn) {
if (newScreenOn) {
// When the user presses the power button, we need to always send out the
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 7dd736d..68bbb571 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -38,6 +38,7 @@ import android.provider.Settings;
import android.server.BluetoothA2dpService;
import android.server.BluetoothService;
import android.server.search.SearchManagerService;
+import android.service.dreams.DreamManagerService;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
@@ -269,6 +270,7 @@ class ServerThread extends Thread {
CountryDetectorService countryDetector = null;
TextServicesManagerService tsms = null;
LockSettingsService lockSettings = null;
+ DreamManagerService dreamy = null;
// Bring up services needed for UI.
if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
@@ -613,6 +615,18 @@ class ServerThread extends Thread {
} catch (Throwable e) {
reportWtf("starting CommonTimeManagementService service", e);
}
+
+ if (context.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableDreams)) {
+ try {
+ Slog.i(TAG, "Dreams Service");
+ // Dreams (interactive idle-time views, a/k/a screen savers)
+ dreamy = new DreamManagerService(context);
+ ServiceManager.addService("dreams", dreamy);
+ } catch (Throwable e) {
+ reportWtf("starting DreamManagerService", e);
+ }
+ }
}
// Before things start rolling, be sure we have decided whether
@@ -699,6 +713,7 @@ class ServerThread extends Thread {
final CommonTimeManagementService commonTimeMgmtServiceF = commonTimeMgmtService;
final TextServicesManagerService textServiceManagerServiceF = tsms;
final StatusBarManagerService statusBarF = statusBar;
+ final DreamManagerService dreamyF = dreamy;
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
@@ -805,6 +820,11 @@ class ServerThread extends Thread {
} catch (Throwable e) {
reportWtf("making Text Services Manager Service ready", e);
}
+ try {
+ if (dreamyF != null) dreamyF.systemReady();
+ } catch (Throwable e) {
+ reportWtf("making DreamManagerService ready", e);
+ }
}
});
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index a7af8fb..00972fa 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -28,6 +28,7 @@ import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
@@ -2131,6 +2132,11 @@ public class WindowManagerService extends IWindowManager.Stub
+ attrs.token + ". Aborting.");
return WindowManagerImpl.ADD_BAD_APP_TOKEN;
}
+ if (attrs.type == TYPE_DREAM) {
+ Slog.w(TAG, "Attempted to add Dream window with unknown token "
+ + attrs.token + ". Aborting.");
+ return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+ }
token = new WindowToken(this, attrs.token, -1, false);
addToken = true;
} else if (attrs.type >= FIRST_APPLICATION_WINDOW
@@ -2163,6 +2169,12 @@ public class WindowManagerService extends IWindowManager.Stub
+ attrs.token + ". Aborting.");
return WindowManagerImpl.ADD_BAD_APP_TOKEN;
}
+ } else if (attrs.type == TYPE_DREAM) {
+ if (token.windowType != TYPE_DREAM) {
+ Slog.w(TAG, "Attempted to add Dream window with bad token "
+ + attrs.token + ". Aborting.");
+ return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+ }
}
win = new WindowState(this, session, client, token,