resolved conflicts for merge of baaa080b
to master
Change-Id: I3ee12321e298f7a2ea577a99f30c49f3bb497fae
This commit is contained in:
@ -183,6 +183,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/print/IWriteResultCallback.aidl \
|
||||
core/java/android/printservice/IPrintService.aidl \
|
||||
core/java/android/printservice/IPrintServiceClient.aidl \
|
||||
core/java/android/service/dreams/IDozeHardware.aidl \
|
||||
core/java/android/service/dreams/IDreamManager.aidl \
|
||||
core/java/android/service/dreams/IDreamService.aidl \
|
||||
core/java/android/service/wallpaper/IWallpaperConnection.aidl \
|
||||
|
@ -190,6 +190,18 @@ public final class PowerManager {
|
||||
*/
|
||||
public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020;
|
||||
|
||||
/**
|
||||
* Wake lock level: Put the screen in a low power state and allow the CPU to suspend
|
||||
* if no other wake locks are held.
|
||||
* <p>
|
||||
* This is used by the dream manager to implement doze mode. It currently
|
||||
* has no effect unless the power manager is in the dozing state.
|
||||
* </p>
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int DOZE_WAKE_LOCK = 0x00000040;
|
||||
|
||||
/**
|
||||
* Mask for the wake lock level component of a combined wake lock level and flags integer.
|
||||
*
|
||||
@ -437,6 +449,7 @@ public final class PowerManager {
|
||||
case SCREEN_BRIGHT_WAKE_LOCK:
|
||||
case FULL_WAKE_LOCK:
|
||||
case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
|
||||
case DOZE_WAKE_LOCK:
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Must specify a valid wake lock level.");
|
||||
|
77
core/java/android/service/dreams/DozeHardware.java
Normal file
77
core/java/android/service/dreams/DozeHardware.java
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright (C) 2014 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.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Provides access to low-level hardware features that a dream may use to provide
|
||||
* a richer user experience while dozing.
|
||||
* <p>
|
||||
* This class contains functions that should be called by the dream to configure
|
||||
* hardware before starting to doze and allowing the application processor to suspend.
|
||||
* For example, the dream may provide the hardware with enough information to render
|
||||
* some content on its own without any further assistance from the application processor.
|
||||
* </p><p>
|
||||
* This object is obtained by calling {@link DreamService#getDozeHardware()}.
|
||||
* </p>
|
||||
*
|
||||
* @hide experimental
|
||||
*/
|
||||
public final class DozeHardware {
|
||||
private static final String TAG = "DozeHardware";
|
||||
|
||||
public static final String MSG_ENABLE_MCU = "enable_mcu";
|
||||
|
||||
public static final byte[] VALUE_ON = "on".getBytes();
|
||||
public static final byte[] VALUE_OFF = "off".getBytes();
|
||||
|
||||
private final IDozeHardware mHardware;
|
||||
|
||||
DozeHardware(IDozeHardware hardware) {
|
||||
mHardware = hardware;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to enable the microcontroller.
|
||||
*
|
||||
* @param enable If true, enables the MCU otherwise disables it.
|
||||
*/
|
||||
public void setEnableMcu(boolean enable) {
|
||||
sendMessage(MSG_ENABLE_MCU, enable ? VALUE_ON : VALUE_OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the doze hardware module.
|
||||
*
|
||||
* @param msg The name of the message to send.
|
||||
* @param arg An optional argument data blob, may be null.
|
||||
* @return A result data blob, may be null.
|
||||
*/
|
||||
public byte[] sendMessage(String msg, byte[] arg) {
|
||||
if (msg == null) {
|
||||
throw new IllegalArgumentException("msg must not be null");
|
||||
}
|
||||
|
||||
try {
|
||||
return mHardware.sendMessage(msg, arg);
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Failed to send message to doze hardware module.", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ public abstract class DreamManagerInternal {
|
||||
/**
|
||||
* Called by the power manager to start a dream.
|
||||
*/
|
||||
public abstract void startDream();
|
||||
public abstract void startDream(boolean doze);
|
||||
|
||||
/**
|
||||
* Called by the power manager to stop a dream.
|
||||
|
@ -20,12 +20,14 @@ import java.io.PrintWriter;
|
||||
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.util.Slog;
|
||||
import android.view.ActionMode;
|
||||
@ -42,6 +44,8 @@ import android.view.WindowManager.LayoutParams;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import com.android.internal.policy.PolicyManager;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.util.DumpUtils.Dump;
|
||||
|
||||
/**
|
||||
* Extend this class to implement a custom dream (available to the user as a "Daydream").
|
||||
@ -145,19 +149,26 @@ public class DreamService extends Service implements Window.Callback {
|
||||
*/
|
||||
public static final String DREAM_META_DATA = "android.service.dream";
|
||||
|
||||
private final IDreamManager mSandman;
|
||||
private final Handler mHandler = new Handler();
|
||||
private IBinder mWindowToken;
|
||||
private Window mWindow;
|
||||
private WindowManager mWindowManager;
|
||||
private IDreamManager mSandman;
|
||||
private boolean mInteractive = false;
|
||||
private boolean mLowProfile = true;
|
||||
private boolean mFullscreen = false;
|
||||
private boolean mScreenBright = true;
|
||||
private boolean mFinished;
|
||||
private boolean mCanDoze;
|
||||
private boolean mDozing;
|
||||
private DozeHardware mDozeHardware;
|
||||
|
||||
private boolean mDebug = false;
|
||||
|
||||
public DreamService() {
|
||||
mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@ -444,9 +455,11 @@ public class DreamService extends Service implements Window.Callback {
|
||||
* correct interactions with it (seeing when it is cleared etc).
|
||||
*/
|
||||
public void setLowProfile(boolean lowProfile) {
|
||||
mLowProfile = lowProfile;
|
||||
int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE;
|
||||
applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag);
|
||||
if (mLowProfile != lowProfile) {
|
||||
mLowProfile = lowProfile;
|
||||
int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE;
|
||||
applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -467,9 +480,11 @@ public class DreamService extends Service implements Window.Callback {
|
||||
* will be cleared.
|
||||
*/
|
||||
public void setFullscreen(boolean fullscreen) {
|
||||
mFullscreen = fullscreen;
|
||||
int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||
applyWindowFlags(mFullscreen ? flag : 0, flag);
|
||||
if (mFullscreen != fullscreen) {
|
||||
mFullscreen = fullscreen;
|
||||
int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||
applyWindowFlags(mFullscreen ? flag : 0, flag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -487,14 +502,16 @@ public class DreamService extends Service implements Window.Callback {
|
||||
* @param screenBright True to keep the screen bright while dreaming.
|
||||
*/
|
||||
public void setScreenBright(boolean screenBright) {
|
||||
mScreenBright = screenBright;
|
||||
int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
||||
applyWindowFlags(mScreenBright ? flag : 0, flag);
|
||||
if (mScreenBright != screenBright) {
|
||||
mScreenBright = screenBright;
|
||||
int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
||||
applyWindowFlags(mScreenBright ? flag : 0, flag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this dream keeps the screen bright while dreaming. Defaults to false,
|
||||
* allowing the screen to dim if necessary.
|
||||
* Returns whether or not this dream keeps the screen bright while dreaming.
|
||||
* Defaults to false, allowing the screen to dim if necessary.
|
||||
*
|
||||
* @see #setScreenBright(boolean)
|
||||
*/
|
||||
@ -502,6 +519,119 @@ public class DreamService extends Service implements Window.Callback {
|
||||
return getWindowFlagValue(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, mScreenBright);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this dream is allowed to doze.
|
||||
* <p>
|
||||
* The value returned by this method is only meaningful when the dream has started.
|
||||
* </p>
|
||||
*
|
||||
* @return True if this dream can doze.
|
||||
* @see #startDozing
|
||||
* @hide experimental
|
||||
*/
|
||||
public boolean canDoze() {
|
||||
return mCanDoze;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts dozing, entering a deep dreamy sleep.
|
||||
* <p>
|
||||
* Dozing enables the system to conserve power while the user is not actively interacting
|
||||
* with the device. While dozing, the display will remain on in a low-power state
|
||||
* and will continue to show its previous contents but the application processor and
|
||||
* other system components will be allowed to suspend when possible.
|
||||
* </p><p>
|
||||
* While the application processor is suspended, the dream may stop executing code
|
||||
* for long periods of time. Prior to being suspended, the dream may schedule periodic
|
||||
* wake-ups to render new content by scheduling an alarm with the {@link AlarmManager}.
|
||||
* The dream may also keep the CPU awake by acquiring a
|
||||
* {@link android.os.PowerManager#PARTIAL_WAKE_LOCK partial wake lock} when necessary.
|
||||
* Note that since the purpose of doze mode is to conserve power (especially when
|
||||
* running on battery), the dream should not wake the CPU very often or keep it
|
||||
* awake for very long.
|
||||
* </p><p>
|
||||
* It is a good idea to call this method some time after the dream's entry animation
|
||||
* has completed and the dream is ready to doze. It is important to completely
|
||||
* finish all of the work needed before dozing since the application processor may
|
||||
* be suspended at any moment once this method is called unless other wake locks
|
||||
* are being held.
|
||||
* </p><p>
|
||||
* Call {@link #stopDozing} or {@link #finish} to stop dozing.
|
||||
* </p>
|
||||
*
|
||||
* @see #stopDozing
|
||||
* @hide experimental
|
||||
*/
|
||||
public void startDozing() {
|
||||
if (mCanDoze && !mDozing) {
|
||||
mDozing = true;
|
||||
try {
|
||||
mSandman.startDozing(mWindowToken);
|
||||
} catch (RemoteException ex) {
|
||||
// system server died
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops dozing, returns to active dreaming.
|
||||
* <p>
|
||||
* This method reverses the effect of {@link #startDozing}. From this moment onward,
|
||||
* the application processor will be kept awake as long as the dream is running
|
||||
* or until the dream starts dozing again.
|
||||
* </p>
|
||||
*
|
||||
* @see #startDozing
|
||||
* @hide experimental
|
||||
*/
|
||||
public void stopDozing() {
|
||||
if (mDozing) {
|
||||
mDozing = false;
|
||||
try {
|
||||
mSandman.stopDozing(mWindowToken);
|
||||
} catch (RemoteException ex) {
|
||||
// system server died
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the dream will allow the system to enter a low-power state while
|
||||
* it is running without actually turning off the screen. Defaults to false,
|
||||
* keeping the application processor awake while the dream is running.
|
||||
*
|
||||
* @return True if the dream is dozing.
|
||||
*
|
||||
* @see #setDozing(boolean)
|
||||
* @hide experimental
|
||||
*/
|
||||
public boolean isDozing() {
|
||||
return mDozing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object that may be used to access low-level hardware features that a
|
||||
* dream may use to provide a richer user experience while dozing.
|
||||
*
|
||||
* @return An instance of {@link DozeHardware} or null if this device does not offer
|
||||
* hardware support for dozing.
|
||||
*
|
||||
* @hide experimental
|
||||
*/
|
||||
public DozeHardware getDozeHardware() {
|
||||
if (mCanDoze && mDozeHardware == null) {
|
||||
try {
|
||||
IDozeHardware hardware = mSandman.getDozeHardware(mWindowToken);
|
||||
if (hardware != null) {
|
||||
mDozeHardware = new DozeHardware(hardware);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
// system server died
|
||||
}
|
||||
}
|
||||
return mDozeHardware;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this Dream is constructed.
|
||||
*/
|
||||
@ -536,7 +666,11 @@ public class DreamService extends Service implements Window.Callback {
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the dream, detaches from the window, and wakes up.
|
||||
* Stops the dream and detaches from the window.
|
||||
* <p>
|
||||
* When the dream ends, the system will be allowed to go to sleep fully unless there
|
||||
* is a reason for it to be awake such as recent user activity or wake locks being held.
|
||||
* </p>
|
||||
*/
|
||||
public final void finish() {
|
||||
if (mDebug) Slog.v(TAG, "finish()");
|
||||
@ -557,10 +691,6 @@ public class DreamService extends Service implements Window.Callback {
|
||||
|
||||
// end public api
|
||||
|
||||
private void loadSandman() {
|
||||
mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by DreamController.stopDream() when the Dream is about to be unbound and destroyed.
|
||||
*
|
||||
@ -572,23 +702,16 @@ public class DreamService extends Service implements Window.Callback {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
onDreamingStopped();
|
||||
} catch (Throwable t) {
|
||||
Slog.w(TAG, "Crashed in onDreamingStopped()", t);
|
||||
// we were going to stop anyway
|
||||
}
|
||||
if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()");
|
||||
onDreamingStopped();
|
||||
|
||||
if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager");
|
||||
try {
|
||||
// force our window to be removed synchronously
|
||||
mWindowManager.removeViewImmediate(mWindow.getDecorView());
|
||||
// the following will print a log message if it finds any other leaked windows
|
||||
WindowManagerGlobal.getInstance().closeAll(mWindowToken,
|
||||
this.getClass().getName(), "Dream");
|
||||
} catch (Throwable t) {
|
||||
Slog.w(TAG, "Crashed removing window view", t);
|
||||
}
|
||||
|
||||
// force our window to be removed synchronously
|
||||
mWindowManager.removeViewImmediate(mWindow.getDecorView());
|
||||
// the following will print a log message if it finds any other leaked windows
|
||||
WindowManagerGlobal.getInstance().closeAll(mWindowToken,
|
||||
this.getClass().getName(), "Dream");
|
||||
|
||||
mWindow = null;
|
||||
mWindowToken = null;
|
||||
@ -601,23 +724,30 @@ public class DreamService extends Service implements Window.Callback {
|
||||
*
|
||||
* @param windowToken A window token that will allow a window to be created in the correct layer.
|
||||
*/
|
||||
private final void attach(IBinder windowToken) {
|
||||
private final void attach(IBinder windowToken, boolean canDoze) {
|
||||
if (mWindowToken != null) {
|
||||
Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
|
||||
return;
|
||||
}
|
||||
if (mFinished) {
|
||||
Slog.w(TAG, "attach() called after dream already finished");
|
||||
try {
|
||||
mSandman.finishSelf(windowToken);
|
||||
} catch (RemoteException ex) {
|
||||
// system server died
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mDebug) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId());
|
||||
|
||||
if (mSandman == null) {
|
||||
loadSandman();
|
||||
}
|
||||
mWindowToken = windowToken;
|
||||
mWindow = PolicyManager.makeNewWindow(this);
|
||||
mWindow.setCallback(this);
|
||||
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
|
||||
mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
|
||||
mWindow.setFormat(PixelFormat.OPAQUE);
|
||||
mCanDoze = canDoze;
|
||||
|
||||
if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
|
||||
windowToken, WindowManager.LayoutParams.TYPE_DREAM));
|
||||
@ -642,40 +772,25 @@ public class DreamService extends Service implements Window.Callback {
|
||||
mWindowManager = mWindow.getWindowManager();
|
||||
|
||||
if (mDebug) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId());
|
||||
try {
|
||||
applySystemUiVisibilityFlags(
|
||||
(mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
|
||||
View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
||||
getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
|
||||
} catch (Throwable t) {
|
||||
Slog.w(TAG, "Crashed adding window view", t);
|
||||
safelyFinish();
|
||||
return;
|
||||
}
|
||||
applySystemUiVisibilityFlags(
|
||||
(mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
|
||||
View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
||||
getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
|
||||
|
||||
// start it up
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
onDreamingStarted();
|
||||
} catch (Throwable t) {
|
||||
Slog.w(TAG, "Crashed in onDreamingStarted()", t);
|
||||
safelyFinish();
|
||||
}
|
||||
if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
|
||||
onDreamingStarted();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void safelyFinish() {
|
||||
if (mDebug) Slog.v(TAG, "safelyFinish()");
|
||||
try {
|
||||
finish();
|
||||
} catch (Throwable t) {
|
||||
Slog.w(TAG, "Crashed in safelyFinish()", t);
|
||||
finishInternal();
|
||||
return;
|
||||
}
|
||||
|
||||
finish();
|
||||
|
||||
if (!mFinished) {
|
||||
Slog.w(TAG, "Bad dream, did not call super.finish()");
|
||||
@ -685,19 +800,21 @@ public class DreamService extends Service implements Window.Callback {
|
||||
|
||||
private void finishInternal() {
|
||||
if (mDebug) Slog.v(TAG, "finishInternal() mFinished = " + mFinished);
|
||||
if (mFinished) return;
|
||||
try {
|
||||
|
||||
if (!mFinished) {
|
||||
mFinished = true;
|
||||
|
||||
if (mSandman != null) {
|
||||
mSandman.finishSelf(mWindowToken);
|
||||
if (mWindowToken == null) {
|
||||
Slog.w(TAG, "Finish was called before the dream was attached.");
|
||||
} else {
|
||||
Slog.w(TAG, "No dream manager found");
|
||||
try {
|
||||
mSandman.finishSelf(mWindowToken);
|
||||
} catch (RemoteException ex) {
|
||||
// system server died
|
||||
}
|
||||
}
|
||||
stopSelf(); // if launched via any other means
|
||||
|
||||
} catch (Throwable t) {
|
||||
Slog.w(TAG, "Crashed in finishInternal()", t);
|
||||
stopSelf(); // if launched via any other means
|
||||
}
|
||||
}
|
||||
|
||||
@ -732,32 +849,39 @@ public class DreamService extends Service implements Window.Callback {
|
||||
|
||||
@Override
|
||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
super.dump(fd, pw, args);
|
||||
|
||||
pw.print(TAG + ": ");
|
||||
if (mWindowToken == null) {
|
||||
pw.println("stopped");
|
||||
} else {
|
||||
pw.println("running (token=" + mWindowToken + ")");
|
||||
}
|
||||
pw.println(" window: " + mWindow);
|
||||
pw.print(" flags:");
|
||||
if (isInteractive()) pw.print(" interactive");
|
||||
if (isLowProfile()) pw.print(" lowprofile");
|
||||
if (isFullscreen()) pw.print(" fullscreen");
|
||||
if (isScreenBright()) pw.print(" bright");
|
||||
pw.println();
|
||||
DumpUtils.dumpAsync(mHandler, new Dump() {
|
||||
@Override
|
||||
public void dump(PrintWriter pw) {
|
||||
pw.print(TAG + ": ");
|
||||
if (mWindowToken == null) {
|
||||
pw.println("stopped");
|
||||
} else {
|
||||
pw.println("running (token=" + mWindowToken + ")");
|
||||
}
|
||||
pw.println(" window: " + mWindow);
|
||||
pw.print(" flags:");
|
||||
if (isInteractive()) pw.print(" interactive");
|
||||
if (isLowProfile()) pw.print(" lowprofile");
|
||||
if (isFullscreen()) pw.print(" fullscreen");
|
||||
if (isScreenBright()) pw.print(" bright");
|
||||
if (isDozing()) pw.print(" dozing");
|
||||
pw.println();
|
||||
}
|
||||
}, pw, 1000);
|
||||
}
|
||||
|
||||
private class DreamServiceWrapper extends IDreamService.Stub {
|
||||
public void attach(final IBinder windowToken) {
|
||||
private final class DreamServiceWrapper extends IDreamService.Stub {
|
||||
@Override
|
||||
public void attach(final IBinder windowToken, final boolean canDoze) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DreamService.this.attach(windowToken);
|
||||
DreamService.this.attach(windowToken, canDoze);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
|
24
core/java/android/service/dreams/IDozeHardware.aidl
Normal file
24
core/java/android/service/dreams/IDozeHardware.aidl
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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
|
||||
*/
|
||||
interface IDozeHardware {
|
||||
byte[] sendMessage(String msg, in byte[] arg);
|
||||
}
|
@ -16,10 +16,11 @@
|
||||
|
||||
package android.service.dreams;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.content.ComponentName;
|
||||
import android.os.IBinder;
|
||||
import android.service.dreams.IDozeHardware;
|
||||
|
||||
/** @hide */
|
||||
interface IDreamManager {
|
||||
@ -31,4 +32,7 @@ interface IDreamManager {
|
||||
void testDream(in ComponentName componentName);
|
||||
boolean isDreaming();
|
||||
void finishSelf(in IBinder token);
|
||||
void startDozing(in IBinder token);
|
||||
void stopDozing(in IBinder token);
|
||||
IDozeHardware getDozeHardware(in IBinder token);
|
||||
}
|
@ -20,6 +20,6 @@ package android.service.dreams;
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IDreamService {
|
||||
void attach(IBinder windowToken);
|
||||
void attach(IBinder windowToken, boolean canDoze);
|
||||
void detach();
|
||||
}
|
||||
|
@ -118,20 +118,6 @@ public interface WindowManagerPolicy {
|
||||
*/
|
||||
public final static int ACTION_PASS_TO_USER = 0x00000001;
|
||||
|
||||
/**
|
||||
* This key event should wake the device.
|
||||
* To be returned from {@link #interceptKeyBeforeQueueing}.
|
||||
* Do not return this and {@link #ACTION_GO_TO_SLEEP} or {@link #ACTION_PASS_TO_USER}.
|
||||
*/
|
||||
public final static int ACTION_WAKE_UP = 0x00000002;
|
||||
|
||||
/**
|
||||
* This key event should put the device to sleep (and engage keyguard if necessary)
|
||||
* To be returned from {@link #interceptKeyBeforeQueueing}.
|
||||
* Do not return this and {@link #ACTION_WAKE_UP} or {@link #ACTION_PASS_TO_USER}.
|
||||
*/
|
||||
public final static int ACTION_GO_TO_SLEEP = 0x00000004;
|
||||
|
||||
/**
|
||||
* Interface to the Window Manager state associated with a particular
|
||||
* window. You can hold on to an instance of this interface from the call
|
||||
@ -760,8 +746,7 @@ public interface WindowManagerPolicy {
|
||||
* @param policyFlags The policy flags associated with the key.
|
||||
* @param isScreenOn True if the screen is already on
|
||||
*
|
||||
* @return The bitwise or of the {@link #ACTION_PASS_TO_USER},
|
||||
* {@link #ACTION_WAKE_UP} and {@link #ACTION_GO_TO_SLEEP} flags.
|
||||
* @return Actions flags: may be {@link #ACTION_PASS_TO_USER}.
|
||||
*/
|
||||
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
|
||||
|
||||
@ -774,10 +759,9 @@ public interface WindowManagerPolicy {
|
||||
* because it's the most fragile.
|
||||
* @param policyFlags The policy flags associated with the motion.
|
||||
*
|
||||
* @return The bitwise or of the {@link #ACTION_PASS_TO_USER},
|
||||
* {@link #ACTION_WAKE_UP} and {@link #ACTION_GO_TO_SLEEP} flags.
|
||||
* @return Actions flags: may be {@link #ACTION_PASS_TO_USER}.
|
||||
*/
|
||||
public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags);
|
||||
public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags);
|
||||
|
||||
/**
|
||||
* Called from the input dispatcher thread before a key is dispatched to a window.
|
||||
|
@ -658,6 +658,11 @@
|
||||
Must be in the range specified by minimum and maximum. -->
|
||||
<integer name="config_screenBrightnessSettingDefault">102</integer>
|
||||
|
||||
<!-- Screen brightness used to dim the screen while dozing in a very low power state.
|
||||
May be less than the minimum allowed brightness setting
|
||||
that can be set by the user. -->
|
||||
<integer name="config_screenBrightnessDoze">1</integer>
|
||||
|
||||
<!-- Screen brightness used to dim the screen when the user activity
|
||||
timeout expires. May be less than the minimum allowed brightness setting
|
||||
that can be set by the user. -->
|
||||
@ -1089,6 +1094,70 @@
|
||||
<!-- ComponentName of the default dream (Settings.Secure.SCREENSAVER_COMPONENT) -->
|
||||
<string name="config_dreamsDefaultComponent">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
|
||||
|
||||
<!-- Are we allowed to dream while not plugged in? -->
|
||||
<bool name="config_dreamsEnabledOnBattery">false</bool>
|
||||
<!-- Minimum battery level to allow dreaming when powered.
|
||||
Use -1 to disable this safety feature. -->
|
||||
<integer name="config_dreamsBatteryLevelMinimumWhenPowered">-1</integer>
|
||||
<!-- Minimum battery level to allow dreaming when not powered.
|
||||
Use -1 to disable this safety feature. -->
|
||||
<integer name="config_dreamsBatteryLevelMinimumWhenNotPowered">15</integer>
|
||||
<!-- If the battery level drops by this percentage and the user activity timeout
|
||||
has expired, then assume the device is receiving insufficient current to charge
|
||||
effectively and terminate the dream. Use -1 to disable this safety feature. -->
|
||||
<integer name="config_dreamsBatteryLevelDrainCutoff">5</integer>
|
||||
|
||||
<!-- ComponentName of a dream to show whenever the system would otherwise have
|
||||
gone to sleep. When the PowerManager is asked to go to sleep, it will instead
|
||||
try to start this dream if possible. The dream should typically call startDozing()
|
||||
to put the display into a low power state and allow the application processor
|
||||
to be suspended. When the dream ends, the system will go to sleep as usual.
|
||||
Specify the component name (Settings.Secure.SCREENSAVER_COMPONENT) or an
|
||||
empty string if none.
|
||||
|
||||
Note that doze dreams are not subject to the same start conditions as ordinary dreams.
|
||||
Doze dreams will run whenever the power manager is in a dozing state. -->
|
||||
<string name="config_dozeComponent"></string>
|
||||
|
||||
<!-- Power Management: Specifies whether to decouple the auto-suspend state of the
|
||||
device from the display on/off state.
|
||||
|
||||
When false, autosuspend_disable() will be called before the display is turned on
|
||||
and autosuspend_enable() will be called after the display is turned off.
|
||||
This mode provides best compatibility for devices using legacy power management
|
||||
features such as early suspend / late resume.
|
||||
|
||||
When true, autosuspend_display() and autosuspend_enable() will be called
|
||||
independently of whether the display is being turned on or off. This mode
|
||||
enables the power manager to suspend the application processor while the
|
||||
display is on.
|
||||
|
||||
This resource should be set to "true" when a doze component has been specified
|
||||
to maximize power savings but not all devices support it.
|
||||
|
||||
Refer to autosuspend.h for details.
|
||||
-->
|
||||
<bool name="config_powerDecoupleAutoSuspendModeFromDisplay">false</bool>
|
||||
|
||||
<!-- Power Management: Specifies whether to decouple the interactive state of the
|
||||
device from the display on/off state.
|
||||
|
||||
When false, setInteractive(..., true) will be called before the display is turned on
|
||||
and setInteractive(..., false) will be called after the display is turned off.
|
||||
This mode provides best compatibility for devices that expect the interactive
|
||||
state to be tied to the display state.
|
||||
|
||||
When true, setInteractive(...) will be called independently of whether the display
|
||||
is being turned on or off. This mode enables the power manager to reduce
|
||||
clocks and disable the touch controller while the display is on.
|
||||
|
||||
This resource should be set to "true" when a doze component has been specified
|
||||
to maximize power savings but not all devices support it.
|
||||
|
||||
Refer to power.h for details.
|
||||
-->
|
||||
<bool name="config_powerDecoupleInteractiveModeFromDisplay">false</bool>
|
||||
|
||||
<!-- Base "touch slop" value used by ViewConfiguration as a
|
||||
movement threshold where scrolling should begin. -->
|
||||
<dimen name="config_viewConfigurationTouchSlop">8dp</dimen>
|
||||
|
@ -1500,6 +1500,7 @@
|
||||
<java-symbol type="integer" name="config_screenBrightnessSettingMaximum" />
|
||||
<java-symbol type="integer" name="config_screenBrightnessSettingDefault" />
|
||||
<java-symbol type="integer" name="config_screenBrightnessDim" />
|
||||
<java-symbol type="integer" name="config_screenBrightnessDoze" />
|
||||
<java-symbol type="integer" name="config_shutdownBatteryTemperature" />
|
||||
<java-symbol type="integer" name="config_undockedHdmiRotation" />
|
||||
<java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" />
|
||||
@ -1604,11 +1605,18 @@
|
||||
<java-symbol type="xml" name="storage_list" />
|
||||
<java-symbol type="bool" name="config_dreamsSupported" />
|
||||
<java-symbol type="bool" name="config_dreamsEnabledByDefault" />
|
||||
<java-symbol type="bool" name="config_dreamsEnabledOnBattery" />
|
||||
<java-symbol type="bool" name="config_dreamsActivatedOnDockByDefault" />
|
||||
<java-symbol type="bool" name="config_dreamsActivatedOnSleepByDefault" />
|
||||
<java-symbol type="integer" name="config_dreamsBatteryLevelMinimumWhenPowered" />
|
||||
<java-symbol type="integer" name="config_dreamsBatteryLevelMinimumWhenNotPowered" />
|
||||
<java-symbol type="integer" name="config_dreamsBatteryLevelDrainCutoff" />
|
||||
<java-symbol type="string" name="config_dreamsDefaultComponent" />
|
||||
<java-symbol type="string" name="config_dozeComponent" />
|
||||
<java-symbol type="string" name="enable_explore_by_touch_warning_title" />
|
||||
<java-symbol type="string" name="enable_explore_by_touch_warning_message" />
|
||||
<java-symbol type="bool" name="config_powerDecoupleAutoSuspendModeFromDisplay" />
|
||||
<java-symbol type="bool" name="config_powerDecoupleInteractiveModeFromDisplay" />
|
||||
|
||||
<java-symbol type="layout" name="resolver_list" />
|
||||
<java-symbol type="id" name="resolver_list" />
|
||||
|
@ -3799,14 +3799,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
if (keyCode == KeyEvent.KEYCODE_POWER) {
|
||||
policyFlags |= WindowManagerPolicy.FLAG_WAKE;
|
||||
}
|
||||
final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
|
||||
| WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
|
||||
|
||||
if (DEBUG_INPUT) {
|
||||
Log.d(TAG, "interceptKeyTq keycode=" + keyCode
|
||||
+ " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive
|
||||
+ " policyFlags=" + Integer.toHexString(policyFlags)
|
||||
+ " isWakeKey=" + isWakeKey);
|
||||
+ " policyFlags=" + Integer.toHexString(policyFlags));
|
||||
}
|
||||
|
||||
if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
|
||||
@ -3823,6 +3820,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
// the device some other way (which is why we have an exemption here for injected
|
||||
// events).
|
||||
int result;
|
||||
boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
|
||||
| WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
|
||||
if (isScreenOn || (isInjected && !isWakeKey)) {
|
||||
// When the screen is on or if the key is injected pass the key to the application.
|
||||
result = ACTION_PASS_TO_USER;
|
||||
@ -3830,8 +3829,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
// When the screen is off and the key is not injected, determine whether
|
||||
// to wake the device but don't pass the key to the application.
|
||||
result = 0;
|
||||
if (down && isWakeKey && isWakeKeyWhenScreenOff(keyCode)) {
|
||||
result |= ACTION_WAKE_UP;
|
||||
if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
|
||||
isWakeKey = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3941,7 +3940,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
}
|
||||
if ((mEndcallBehavior
|
||||
& Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
|
||||
result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
|
||||
mPowerManager.goToSleep(event.getEventTime());
|
||||
isWakeKey = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3988,7 +3988,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
mPowerKeyTriggered = false;
|
||||
cancelPendingScreenshotChordAction();
|
||||
if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
|
||||
result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
|
||||
mPowerManager.goToSleep(event.getEventTime());
|
||||
isWakeKey = false;
|
||||
}
|
||||
mPendingPowerKeyUpCanceled = false;
|
||||
}
|
||||
@ -4058,6 +4059,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isWakeKey) {
|
||||
mPowerManager.wakeUp(event.getEventTime());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -4098,13 +4103,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
|
||||
public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) {
|
||||
int result = 0;
|
||||
|
||||
final boolean isWakeMotion = (policyFlags
|
||||
& (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
|
||||
if (isWakeMotion) {
|
||||
result |= ACTION_WAKE_UP;
|
||||
mPowerManager.wakeUp(whenNanos / 1000000);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ final class DreamController {
|
||||
pw.println(" mToken=" + mCurrentDream.mToken);
|
||||
pw.println(" mName=" + mCurrentDream.mName);
|
||||
pw.println(" mIsTest=" + mCurrentDream.mIsTest);
|
||||
pw.println(" mCanDoze=" + mCurrentDream.mCanDoze);
|
||||
pw.println(" mUserId=" + mCurrentDream.mUserId);
|
||||
pw.println(" mBound=" + mCurrentDream.mBound);
|
||||
pw.println(" mService=" + mCurrentDream.mService);
|
||||
@ -94,15 +95,18 @@ final class DreamController {
|
||||
}
|
||||
}
|
||||
|
||||
public void startDream(Binder token, ComponentName name, boolean isTest, int userId) {
|
||||
public void startDream(Binder token, ComponentName name,
|
||||
boolean isTest, boolean canDoze, int userId) {
|
||||
stopDream();
|
||||
|
||||
// Close the notification shade. Don't need to send to all, but better to be explicit.
|
||||
mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL);
|
||||
|
||||
Slog.i(TAG, "Starting dream: name=" + name + ", isTest=" + isTest + ", userId=" + userId);
|
||||
Slog.i(TAG, "Starting dream: name=" + name
|
||||
+ ", isTest=" + isTest + ", canDoze=" + canDoze
|
||||
+ ", userId=" + userId);
|
||||
|
||||
mCurrentDream = new DreamRecord(token, name, isTest, userId);
|
||||
mCurrentDream = new DreamRecord(token, name, isTest, canDoze, userId);
|
||||
|
||||
try {
|
||||
mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM);
|
||||
@ -140,7 +144,8 @@ final class DreamController {
|
||||
final DreamRecord oldDream = mCurrentDream;
|
||||
mCurrentDream = null;
|
||||
Slog.i(TAG, "Stopping dream: name=" + oldDream.mName
|
||||
+ ", isTest=" + oldDream.mIsTest + ", userId=" + oldDream.mUserId);
|
||||
+ ", isTest=" + oldDream.mIsTest + ", canDoze=" + oldDream.mCanDoze
|
||||
+ ", userId=" + oldDream.mUserId);
|
||||
|
||||
mHandler.removeCallbacks(mStopUnconnectedDreamRunnable);
|
||||
|
||||
@ -187,7 +192,7 @@ final class DreamController {
|
||||
private void attach(IDreamService service) {
|
||||
try {
|
||||
service.asBinder().linkToDeath(mCurrentDream, 0);
|
||||
service.attach(mCurrentDream.mToken);
|
||||
service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze);
|
||||
} catch (RemoteException ex) {
|
||||
Slog.e(TAG, "The dream service died unexpectedly.", ex);
|
||||
stopDream();
|
||||
@ -213,6 +218,7 @@ final class DreamController {
|
||||
public final Binder mToken;
|
||||
public final ComponentName mName;
|
||||
public final boolean mIsTest;
|
||||
public final boolean mCanDoze;
|
||||
public final int mUserId;
|
||||
|
||||
public boolean mBound;
|
||||
@ -221,10 +227,11 @@ final class DreamController {
|
||||
public boolean mSentStartBroadcast;
|
||||
|
||||
public DreamRecord(Binder token, ComponentName name,
|
||||
boolean isTest, int userId) {
|
||||
boolean isTest, boolean canDoze, int userId) {
|
||||
mToken = token;
|
||||
mName = name;
|
||||
mIsTest = isTest;
|
||||
mCanDoze = canDoze;
|
||||
mUserId = userId;
|
||||
}
|
||||
|
||||
|
@ -30,16 +30,20 @@ import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.service.dreams.DreamManagerInternal;
|
||||
import android.service.dreams.DreamService;
|
||||
import android.service.dreams.IDozeHardware;
|
||||
import android.service.dreams.IDreamManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
@ -64,11 +68,16 @@ public final class DreamManagerService extends SystemService {
|
||||
private final DreamHandler mHandler;
|
||||
private final DreamController mController;
|
||||
private final PowerManager mPowerManager;
|
||||
private final PowerManager.WakeLock mDozeWakeLock;
|
||||
private final McuHal mMcuHal; // synchronized on self
|
||||
|
||||
private Binder mCurrentDreamToken;
|
||||
private ComponentName mCurrentDreamName;
|
||||
private int mCurrentDreamUserId;
|
||||
private boolean mCurrentDreamIsTest;
|
||||
private boolean mCurrentDreamCanDoze;
|
||||
private boolean mCurrentDreamIsDozing;
|
||||
private DozeHardwareWrapper mCurrentDreamDozeHardware;
|
||||
|
||||
public DreamManagerService(Context context) {
|
||||
super(context);
|
||||
@ -77,6 +86,12 @@ public final class DreamManagerService extends SystemService {
|
||||
mController = new DreamController(context, mHandler, mControllerListener);
|
||||
|
||||
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
|
||||
mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG);
|
||||
|
||||
mMcuHal = McuHal.open();
|
||||
if (mMcuHal != null) {
|
||||
mMcuHal.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -103,10 +118,15 @@ public final class DreamManagerService extends SystemService {
|
||||
pw.println("DREAM MANAGER (dumpsys dreams)");
|
||||
pw.println();
|
||||
|
||||
pw.println("mMcuHal=" + mMcuHal);
|
||||
pw.println();
|
||||
pw.println("mCurrentDreamToken=" + mCurrentDreamToken);
|
||||
pw.println("mCurrentDreamName=" + mCurrentDreamName);
|
||||
pw.println("mCurrentDreamUserId=" + mCurrentDreamUserId);
|
||||
pw.println("mCurrentDreamIsTest=" + mCurrentDreamIsTest);
|
||||
pw.println("mCurrentDreamCanDoze=" + mCurrentDreamCanDoze);
|
||||
pw.println("mCurrentDreamIsDozing=" + mCurrentDreamIsDozing);
|
||||
pw.println("mCurrentDreamDozeHardware=" + mCurrentDreamDozeHardware);
|
||||
pw.println();
|
||||
|
||||
DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() {
|
||||
@ -163,16 +183,16 @@ public final class DreamManagerService extends SystemService {
|
||||
|
||||
private void testDreamInternal(ComponentName dream, int userId) {
|
||||
synchronized (mLock) {
|
||||
startDreamLocked(dream, true /*isTest*/, userId);
|
||||
startDreamLocked(dream, true /*isTest*/, false /*canDoze*/, userId);
|
||||
}
|
||||
}
|
||||
|
||||
private void startDreamInternal() {
|
||||
int userId = ActivityManager.getCurrentUser();
|
||||
ComponentName dream = chooseDreamForUser(userId);
|
||||
private void startDreamInternal(boolean doze) {
|
||||
final int userId = ActivityManager.getCurrentUser();
|
||||
final ComponentName dream = doze ? getDozeComponent() : chooseDreamForUser(userId);
|
||||
if (dream != null) {
|
||||
synchronized (mLock) {
|
||||
startDreamLocked(dream, false /*isTest*/, userId);
|
||||
startDreamLocked(dream, false /*isTest*/, doze, userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -183,6 +203,44 @@ public final class DreamManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private void startDozingInternal(IBinder token) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Dream requested to start dozing: " + token);
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
if (mCurrentDreamToken == token && mCurrentDreamCanDoze
|
||||
&& !mCurrentDreamIsDozing) {
|
||||
mCurrentDreamIsDozing = true;
|
||||
mDozeWakeLock.acquire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void stopDozingInternal(IBinder token) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Dream requested to stop dozing: " + token);
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
if (mCurrentDreamToken == token && mCurrentDreamIsDozing) {
|
||||
mCurrentDreamIsDozing = false;
|
||||
mDozeWakeLock.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IDozeHardware getDozeHardwareInternal(IBinder token) {
|
||||
synchronized (mLock) {
|
||||
if (mCurrentDreamToken == token && mCurrentDreamCanDoze
|
||||
&& mCurrentDreamDozeHardware == null && mMcuHal != null) {
|
||||
mCurrentDreamDozeHardware = new DozeHardwareWrapper();
|
||||
return mCurrentDreamDozeHardware;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ComponentName chooseDreamForUser(int userId) {
|
||||
ComponentName[] dreams = getDreamComponentsForUser(userId);
|
||||
return dreams != null && dreams.length != 0 ? dreams[0] : null;
|
||||
@ -231,6 +289,20 @@ public final class DreamManagerService extends SystemService {
|
||||
return name == null ? null : ComponentName.unflattenFromString(name);
|
||||
}
|
||||
|
||||
private ComponentName getDozeComponent() {
|
||||
// Read the component from a system property to facilitate debugging.
|
||||
// Note that for production devices, the dream should actually be declared in
|
||||
// a config.xml resource.
|
||||
String name = Build.IS_DEBUGGABLE ? SystemProperties.get("debug.doze.component") : null;
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
// Read the component from a config.xml resource.
|
||||
// The value should be specified in a resource overlay for the product.
|
||||
name = mContext.getResources().getString(
|
||||
com.android.internal.R.string.config_dozeComponent);
|
||||
}
|
||||
return TextUtils.isEmpty(name) ? null : ComponentName.unflattenFromString(name);
|
||||
}
|
||||
|
||||
private boolean serviceExists(ComponentName name) {
|
||||
try {
|
||||
return name != null && mContext.getPackageManager().getServiceInfo(name, 0) != null;
|
||||
@ -240,9 +312,10 @@ public final class DreamManagerService extends SystemService {
|
||||
}
|
||||
|
||||
private void startDreamLocked(final ComponentName name,
|
||||
final boolean isTest, final int userId) {
|
||||
final boolean isTest, final boolean canDoze, final int userId) {
|
||||
if (Objects.equal(mCurrentDreamName, name)
|
||||
&& mCurrentDreamIsTest == isTest
|
||||
&& mCurrentDreamCanDoze == canDoze
|
||||
&& mCurrentDreamUserId == userId) {
|
||||
return;
|
||||
}
|
||||
@ -255,12 +328,13 @@ public final class DreamManagerService extends SystemService {
|
||||
mCurrentDreamToken = newToken;
|
||||
mCurrentDreamName = name;
|
||||
mCurrentDreamIsTest = isTest;
|
||||
mCurrentDreamCanDoze = canDoze;
|
||||
mCurrentDreamUserId = userId;
|
||||
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mController.startDream(newToken, name, isTest, userId);
|
||||
mController.startDream(newToken, name, isTest, canDoze, userId);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -284,7 +358,16 @@ public final class DreamManagerService extends SystemService {
|
||||
mCurrentDreamToken = null;
|
||||
mCurrentDreamName = null;
|
||||
mCurrentDreamIsTest = false;
|
||||
mCurrentDreamCanDoze = false;
|
||||
mCurrentDreamUserId = 0;
|
||||
if (mCurrentDreamIsDozing) {
|
||||
mCurrentDreamIsDozing = false;
|
||||
mDozeWakeLock.release();
|
||||
}
|
||||
if (mCurrentDreamDozeHardware != null) {
|
||||
mCurrentDreamDozeHardware.release();
|
||||
mCurrentDreamDozeHardware = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPermission(String permission) {
|
||||
@ -473,12 +556,57 @@ public final class DreamManagerService extends SystemService {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void startDozing(IBinder token) {
|
||||
// Requires no permission, called by Dream from an arbitrary process.
|
||||
if (token == null) {
|
||||
throw new IllegalArgumentException("token must not be null");
|
||||
}
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
startDozingInternal(token);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void stopDozing(IBinder token) {
|
||||
// Requires no permission, called by Dream from an arbitrary process.
|
||||
if (token == null) {
|
||||
throw new IllegalArgumentException("token must not be null");
|
||||
}
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
stopDozingInternal(token);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public IDozeHardware getDozeHardware(IBinder token) {
|
||||
// Requires no permission, called by Dream from an arbitrary process.
|
||||
if (token == null) {
|
||||
throw new IllegalArgumentException("token must not be null");
|
||||
}
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return getDozeHardwareInternal(token);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class LocalService extends DreamManagerInternal {
|
||||
@Override
|
||||
public void startDream() {
|
||||
startDreamInternal();
|
||||
public void startDream(boolean doze) {
|
||||
startDreamInternal(doze);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -491,4 +619,37 @@ public final class DreamManagerService extends SystemService {
|
||||
return isDreamingInternal();
|
||||
}
|
||||
}
|
||||
|
||||
private final class DozeHardwareWrapper extends IDozeHardware.Stub {
|
||||
private boolean mReleased;
|
||||
|
||||
public void release() {
|
||||
synchronized (mMcuHal) {
|
||||
if (!mReleased) {
|
||||
mReleased = true;
|
||||
mMcuHal.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public byte[] sendMessage(String msg, byte[] arg) {
|
||||
if (msg == null) {
|
||||
throw new IllegalArgumentException("msg must not be null");
|
||||
}
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mMcuHal) {
|
||||
if (mReleased) {
|
||||
throw new IllegalStateException("This operation cannot be performed "
|
||||
+ "because the dream has ended.");
|
||||
}
|
||||
return mMcuHal.sendMessage(msg, arg);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
46
services/core/java/com/android/server/dreams/McuHal.java
Normal file
46
services/core/java/com/android/server/dreams/McuHal.java
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.server.dreams;
|
||||
|
||||
import android.service.dreams.DozeHardware;
|
||||
|
||||
/**
|
||||
* Provides access to the low-level microcontroller hardware abstraction layer.
|
||||
*/
|
||||
final class McuHal {
|
||||
private final long mPtr;
|
||||
|
||||
private static native long nativeOpen();
|
||||
private static native byte[] nativeSendMessage(long ptr, String msg, byte[] arg);
|
||||
|
||||
private McuHal(long ptr) {
|
||||
mPtr = ptr;
|
||||
}
|
||||
|
||||
public static McuHal open() {
|
||||
long ptr = nativeOpen();
|
||||
return ptr != 0 ? new McuHal(ptr) : null;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
sendMessage(DozeHardware.MSG_ENABLE_MCU, DozeHardware.VALUE_OFF);
|
||||
}
|
||||
|
||||
public byte[] sendMessage(String msg, byte[] arg) {
|
||||
return nativeSendMessage(mPtr, msg, arg);
|
||||
}
|
||||
}
|
@ -1366,8 +1366,9 @@ public class InputManagerService extends IInputManager.Stub
|
||||
}
|
||||
|
||||
// Native callback.
|
||||
private int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
|
||||
return mWindowManagerCallbacks.interceptMotionBeforeQueueingWhenScreenOff(policyFlags);
|
||||
private int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) {
|
||||
return mWindowManagerCallbacks.interceptMotionBeforeQueueingWhenScreenOff(
|
||||
whenNanos, policyFlags);
|
||||
}
|
||||
|
||||
// Native callback.
|
||||
@ -1527,7 +1528,7 @@ public class InputManagerService extends IInputManager.Stub
|
||||
|
||||
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
|
||||
|
||||
public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags);
|
||||
public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags);
|
||||
|
||||
public long interceptKeyBeforeDispatching(InputWindowHandle focus,
|
||||
KeyEvent event, int policyFlags);
|
||||
|
@ -201,7 +201,7 @@ class AutomaticBrightnessController {
|
||||
public void updatePowerState(DisplayPowerRequest request) {
|
||||
if (setScreenAutoBrightnessAdjustment(request.screenAutoBrightnessAdjustment)
|
||||
|| setLightSensorEnabled(request.useAutoBrightness
|
||||
&& DisplayPowerRequest.wantScreenOn(request.screenState))) {
|
||||
&& request.wantScreenOnNormal())) {
|
||||
updateAutoBrightness(false /*sendUpdate*/);
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +147,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
// The proximity sensor, or null if not available or needed.
|
||||
private Sensor mProximitySensor;
|
||||
|
||||
// The doze screen brightness.
|
||||
private final int mScreenBrightnessDozeConfig;
|
||||
|
||||
// The dim screen brightness.
|
||||
private final int mScreenBrightnessDimConfig;
|
||||
|
||||
@ -259,6 +262,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
|
||||
final Resources resources = context.getResources();
|
||||
|
||||
mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger(
|
||||
com.android.internal.R.integer.config_screenBrightnessDoze));
|
||||
|
||||
mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
|
||||
com.android.internal.R.integer.config_screenBrightnessDim));
|
||||
|
||||
@ -432,7 +438,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
// Update the power state request.
|
||||
final boolean mustNotify;
|
||||
boolean mustInitialize = false;
|
||||
boolean wasDim = false;
|
||||
boolean wasDimOrDoze = false;
|
||||
|
||||
synchronized (mLock) {
|
||||
mPendingUpdatePowerStateLocked = false;
|
||||
@ -447,7 +453,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mPendingRequestChangedLocked = false;
|
||||
mustInitialize = true;
|
||||
} else if (mPendingRequestChangedLocked) {
|
||||
wasDim = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM);
|
||||
wasDimOrDoze = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM
|
||||
|| mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE);
|
||||
mPowerRequest.copyFrom(mPendingRequestLocked);
|
||||
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
|
||||
mPendingWaitForNegativeProximityLocked = false;
|
||||
@ -498,7 +505,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
}
|
||||
|
||||
// Set the screen brightness.
|
||||
if (DisplayPowerRequest.wantScreenOn(mPowerRequest.screenState)) {
|
||||
if (mPowerRequest.wantScreenOnAny()) {
|
||||
int target;
|
||||
boolean slow;
|
||||
int screenAutoBrightness = mAutomaticBrightnessController != null ?
|
||||
@ -517,12 +524,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
slow = false;
|
||||
mUsingScreenAutoBrightness = false;
|
||||
}
|
||||
if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
|
||||
if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE) {
|
||||
// Dim quickly to the doze state.
|
||||
target = mScreenBrightnessDozeConfig;
|
||||
slow = false;
|
||||
} else if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
|
||||
// Dim quickly by at least some minimum amount.
|
||||
target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION,
|
||||
mScreenBrightnessDimConfig);
|
||||
slow = false;
|
||||
} else if (wasDim) {
|
||||
} else if (wasDimOrDoze) {
|
||||
// Brighten quickly.
|
||||
slow = false;
|
||||
}
|
||||
@ -535,7 +546,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
|
||||
// Animate the screen on or off.
|
||||
if (!mScreenOffBecauseOfProximity) {
|
||||
if (DisplayPowerRequest.wantScreenOn(mPowerRequest.screenState)) {
|
||||
if (mPowerRequest.wantScreenOnAny()) {
|
||||
// Want screen on.
|
||||
// Wait for previous off animation to complete beforehand.
|
||||
// It is relatively short but if we cancel it and switch to the
|
||||
@ -804,6 +815,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
|
||||
pw.println();
|
||||
pw.println("Display Controller Configuration:");
|
||||
pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
|
||||
pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
|
||||
pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
|
||||
pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
|
||||
|
@ -30,10 +30,11 @@ import android.os.PowerManager;
|
||||
*/
|
||||
final class DisplayPowerRequest {
|
||||
public static final int SCREEN_STATE_OFF = 0;
|
||||
public static final int SCREEN_STATE_DIM = 1;
|
||||
public static final int SCREEN_STATE_BRIGHT = 2;
|
||||
public static final int SCREEN_STATE_DOZE = 1;
|
||||
public static final int SCREEN_STATE_DIM = 2;
|
||||
public static final int SCREEN_STATE_BRIGHT = 3;
|
||||
|
||||
// The requested minimum screen power state: off, dim or bright.
|
||||
// The requested minimum screen power state: off, doze, dim or bright.
|
||||
public int screenState;
|
||||
|
||||
// If true, the proximity sensor overrides the screen state when an object is
|
||||
@ -75,6 +76,23 @@ final class DisplayPowerRequest {
|
||||
copyFrom(other);
|
||||
}
|
||||
|
||||
// Returns true if we want the screen on in any mode, including doze.
|
||||
public boolean wantScreenOnAny() {
|
||||
return screenState != SCREEN_STATE_OFF;
|
||||
}
|
||||
|
||||
// Returns true if we want the screen on in a normal mode, excluding doze.
|
||||
// This is usually what we want to tell the rest of the system. For compatibility
|
||||
// reasons, we pretend the screen is off when dozing.
|
||||
public boolean wantScreenOnNormal() {
|
||||
return screenState == SCREEN_STATE_DIM || screenState == SCREEN_STATE_BRIGHT;
|
||||
}
|
||||
|
||||
public boolean wantLightSensorEnabled() {
|
||||
// Specifically, we don't want the light sensor while dozing.
|
||||
return useAutoBrightness && wantScreenOnNormal();
|
||||
}
|
||||
|
||||
public void copyFrom(DisplayPowerRequest other) {
|
||||
screenState = other.screenState;
|
||||
useProximitySensor = other.useProximitySensor;
|
||||
|
@ -83,7 +83,7 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
|
||||
// Message: Sent when a user activity timeout occurs to update the power state.
|
||||
private static final int MSG_USER_ACTIVITY_TIMEOUT = 1;
|
||||
// Message: Sent when the device enters or exits a napping or dreaming state.
|
||||
// Message: Sent when the device enters or exits a dreaming or dozing state.
|
||||
private static final int MSG_SANDMAN = 2;
|
||||
// Message: Sent when the screen on blocker is released.
|
||||
private static final int MSG_SCREEN_ON_BLOCKER_RELEASED = 3;
|
||||
@ -117,19 +117,21 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
|
||||
// Wakefulness: The device is asleep and can only be awoken by a call to wakeUp().
|
||||
// The screen should be off or in the process of being turned off by the display controller.
|
||||
// The device typically passes through the dozing state first.
|
||||
private static final int WAKEFULNESS_ASLEEP = 0;
|
||||
// Wakefulness: The device is fully awake. It can be put to sleep by a call to goToSleep().
|
||||
// When the user activity timeout expires, the device may start napping or go to sleep.
|
||||
// When the user activity timeout expires, the device may start dreaming or go to sleep.
|
||||
private static final int WAKEFULNESS_AWAKE = 1;
|
||||
// Wakefulness: The device is napping. It is deciding whether to dream or go to sleep
|
||||
// but hasn't gotten around to it yet. It can be awoken by a call to wakeUp(), which
|
||||
// ends the nap. User activity may brighten the screen but does not end the nap.
|
||||
private static final int WAKEFULNESS_NAPPING = 2;
|
||||
// Wakefulness: The device is dreaming. It can be awoken by a call to wakeUp(),
|
||||
// which ends the dream. The device goes to sleep when goToSleep() is called, when
|
||||
// the dream ends or when unplugged.
|
||||
// User activity may brighten the screen but does not end the dream.
|
||||
private static final int WAKEFULNESS_DREAMING = 3;
|
||||
private static final int WAKEFULNESS_DREAMING = 2;
|
||||
// Wakefulness: The device is dozing. It is almost asleep but is allowing a special
|
||||
// low-power "doze" dream to run which keeps the display on but lets the application
|
||||
// processor be suspended. It can be awoken by a call to wakeUp() which ends the dream.
|
||||
// The device fully goes to sleep if the dream cannot be started or ends on its own.
|
||||
private static final int WAKEFULNESS_DOZING = 3;
|
||||
|
||||
// Summarizes the state of all active wakelocks.
|
||||
private static final int WAKE_LOCK_CPU = 1 << 0;
|
||||
@ -138,6 +140,7 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
private static final int WAKE_LOCK_BUTTON_BRIGHT = 1 << 3;
|
||||
private static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
|
||||
private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
|
||||
private static final int WAKE_LOCK_DOZE = 1 << 6;
|
||||
|
||||
// Summarizes the user activity state.
|
||||
private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
|
||||
@ -164,11 +167,6 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
// Poll interval in milliseconds for watching boot animation finished.
|
||||
private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
|
||||
|
||||
// If the battery level drops by this percentage and the user activity timeout
|
||||
// has expired, then assume the device is receiving insufficient current to charge
|
||||
// effectively and terminate the dream.
|
||||
private static final int DREAM_BATTERY_LEVEL_DRAIN_CUTOFF = 5;
|
||||
|
||||
private final Context mContext;
|
||||
private LightsManager mLightsManager;
|
||||
private BatteryService mBatteryService;
|
||||
@ -195,6 +193,10 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
// This is distinct from the screen power state, which is managed separately.
|
||||
private int mWakefulness;
|
||||
|
||||
// True if the sandman has just been summoned for the first time since entering the
|
||||
// dreaming or dozing state. Indicates whether a new dream should begin.
|
||||
private boolean mSandmanSummoned;
|
||||
|
||||
// True if MSG_SANDMAN has been scheduled.
|
||||
private boolean mSandmanScheduled;
|
||||
|
||||
@ -265,6 +267,14 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
// True if boot completed occurred. We keep the screen on until this happens.
|
||||
private boolean mBootCompleted;
|
||||
|
||||
// True if auto-suspend mode is enabled.
|
||||
// Refer to autosuspend.h.
|
||||
private boolean mAutoSuspendModeEnabled;
|
||||
|
||||
// True if interactive mode is enabled.
|
||||
// Refer to power.h.
|
||||
private boolean mInteractiveModeEnabled;
|
||||
|
||||
// True if the device is plugged into a power source.
|
||||
private boolean mIsPowered;
|
||||
|
||||
@ -282,6 +292,12 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
// The current dock state.
|
||||
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
|
||||
|
||||
// True to decouple auto-suspend mode from the display state.
|
||||
private boolean mDecoupleAutoSuspendModeFromDisplayConfig;
|
||||
|
||||
// True to decouple interactive mode from the display state.
|
||||
private boolean mDecoupleInteractiveModeFromDisplayConfig;
|
||||
|
||||
// True if the device should wake up when plugged or unplugged.
|
||||
private boolean mWakeUpWhenPluggedOrUnpluggedConfig;
|
||||
|
||||
@ -300,6 +316,22 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
// Default value for dreams activate-on-dock
|
||||
private boolean mDreamsActivatedOnDockByDefaultConfig;
|
||||
|
||||
// True if dreams can run while not plugged in.
|
||||
private boolean mDreamsEnabledOnBatteryConfig;
|
||||
|
||||
// Minimum battery level to allow dreaming when powered.
|
||||
// Use -1 to disable this safety feature.
|
||||
private int mDreamsBatteryLevelMinimumWhenPoweredConfig;
|
||||
|
||||
// Minimum battery level to allow dreaming when not powered.
|
||||
// Use -1 to disable this safety feature.
|
||||
private int mDreamsBatteryLevelMinimumWhenNotPoweredConfig;
|
||||
|
||||
// If the battery level drops by this percentage and the user activity timeout
|
||||
// has expired, then assume the device is receiving insufficient current to charge
|
||||
// effectively and terminate the dream. Use -1 to disable this safety feature.
|
||||
private int mDreamsBatteryLevelDrainCutoffConfig;
|
||||
|
||||
// True if dreams are enabled by the user.
|
||||
private boolean mDreamsEnabledSetting;
|
||||
|
||||
@ -523,6 +555,10 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
private void readConfigurationLocked() {
|
||||
final Resources resources = mContext.getResources();
|
||||
|
||||
mDecoupleAutoSuspendModeFromDisplayConfig = resources.getBoolean(
|
||||
com.android.internal.R.bool.config_powerDecoupleAutoSuspendModeFromDisplay);
|
||||
mDecoupleInteractiveModeFromDisplayConfig = resources.getBoolean(
|
||||
com.android.internal.R.bool.config_powerDecoupleInteractiveModeFromDisplay);
|
||||
mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
|
||||
com.android.internal.R.bool.config_unplugTurnsOnScreen);
|
||||
mSuspendWhenScreenOffDueToProximityConfig = resources.getBoolean(
|
||||
@ -535,6 +571,14 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
|
||||
mDreamsActivatedOnDockByDefaultConfig = resources.getBoolean(
|
||||
com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
|
||||
mDreamsEnabledOnBatteryConfig = resources.getBoolean(
|
||||
com.android.internal.R.bool.config_dreamsEnabledOnBattery);
|
||||
mDreamsBatteryLevelMinimumWhenPoweredConfig = resources.getInteger(
|
||||
com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenPowered);
|
||||
mDreamsBatteryLevelMinimumWhenNotPoweredConfig = resources.getInteger(
|
||||
com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenNotPowered);
|
||||
mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger(
|
||||
com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff);
|
||||
}
|
||||
|
||||
private void updateSettingsLocked() {
|
||||
@ -762,6 +806,7 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
case PowerManager.SCREEN_DIM_WAKE_LOCK:
|
||||
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
|
||||
case PowerManager.FULL_WAKE_LOCK:
|
||||
case PowerManager.DOZE_WAKE_LOCK:
|
||||
return true;
|
||||
|
||||
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
|
||||
@ -794,7 +839,8 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
}
|
||||
|
||||
if (eventTime < mLastSleepTime || eventTime < mLastWakeTime
|
||||
|| mWakefulness == WAKEFULNESS_ASLEEP || !mBootCompleted || !mSystemReady) {
|
||||
|| mWakefulness == WAKEFULNESS_ASLEEP || mWakefulness == WAKEFULNESS_DOZING
|
||||
|| !mBootCompleted || !mSystemReady) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -843,18 +889,21 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
switch (mWakefulness) {
|
||||
case WAKEFULNESS_ASLEEP:
|
||||
Slog.i(TAG, "Waking up from sleep...");
|
||||
sendPendingNotificationsLocked();
|
||||
mNotifier.onWakeUpStarted();
|
||||
mSendWakeUpFinishedNotificationWhenReady = true;
|
||||
break;
|
||||
case WAKEFULNESS_DREAMING:
|
||||
Slog.i(TAG, "Waking up from dream...");
|
||||
break;
|
||||
case WAKEFULNESS_NAPPING:
|
||||
Slog.i(TAG, "Waking up from nap...");
|
||||
case WAKEFULNESS_DOZING:
|
||||
Slog.i(TAG, "Waking up from dozing...");
|
||||
break;
|
||||
}
|
||||
|
||||
if (mWakefulness != WAKEFULNESS_DREAMING) {
|
||||
sendPendingNotificationsLocked();
|
||||
mNotifier.onWakeUpStarted();
|
||||
mSendWakeUpFinishedNotificationWhenReady = true;
|
||||
}
|
||||
|
||||
mLastWakeTime = eventTime;
|
||||
mWakefulness = WAKEFULNESS_AWAKE;
|
||||
mDirty |= DIRTY_WAKEFULNESS;
|
||||
@ -877,13 +926,17 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
}
|
||||
}
|
||||
|
||||
// This method is called goToSleep for historical reasons but we actually start
|
||||
// dozing before really going to sleep.
|
||||
@SuppressWarnings("deprecation")
|
||||
private boolean goToSleepNoUpdateLocked(long eventTime, int reason) {
|
||||
if (DEBUG_SPEW) {
|
||||
Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime + ", reason=" + reason);
|
||||
}
|
||||
|
||||
if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
|
||||
if (eventTime < mLastWakeTime
|
||||
|| mWakefulness == WAKEFULNESS_ASLEEP
|
||||
|| mWakefulness == WAKEFULNESS_DOZING
|
||||
|| !mBootCompleted || !mSystemReady) {
|
||||
return false;
|
||||
}
|
||||
@ -907,7 +960,8 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
|
||||
mLastSleepTime = eventTime;
|
||||
mDirty |= DIRTY_WAKEFULNESS;
|
||||
mWakefulness = WAKEFULNESS_ASLEEP;
|
||||
mWakefulness = WAKEFULNESS_DOZING;
|
||||
mSandmanSummoned = true;
|
||||
|
||||
// Report the number of wake locks that will be cleared by going to sleep.
|
||||
int numWakeLocksCleared = 0;
|
||||
@ -947,7 +1001,26 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
Slog.i(TAG, "Nap time...");
|
||||
|
||||
mDirty |= DIRTY_WAKEFULNESS;
|
||||
mWakefulness = WAKEFULNESS_NAPPING;
|
||||
mWakefulness = WAKEFULNESS_DREAMING;
|
||||
mSandmanSummoned = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Done dozing, drop everything and go to sleep.
|
||||
private boolean reallyGoToSleepNoUpdateLocked(long eventTime) {
|
||||
if (DEBUG_SPEW) {
|
||||
Slog.d(TAG, "reallyGoToSleepNoUpdateLocked: eventTime=" + eventTime);
|
||||
}
|
||||
|
||||
if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
|
||||
|| !mBootCompleted || !mSystemReady) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Slog.i(TAG, "Sleeping...");
|
||||
|
||||
mDirty |= DIRTY_WAKEFULNESS;
|
||||
mWakefulness = WAKEFULNESS_ASLEEP;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1023,7 +1096,7 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
mPlugType = mBatteryService.getPlugType();
|
||||
mBatteryLevel = mBatteryService.getBatteryLevel();
|
||||
|
||||
if (DEBUG) {
|
||||
if (DEBUG_SPEW) {
|
||||
Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered
|
||||
+ ", mIsPowered=" + mIsPowered
|
||||
+ ", oldPlugType=" + oldPlugType
|
||||
@ -1083,8 +1156,7 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
}
|
||||
|
||||
// If already dreaming and becoming powered, then don't wake.
|
||||
if (mIsPowered && (mWakefulness == WAKEFULNESS_NAPPING
|
||||
|| mWakefulness == WAKEFULNESS_DREAMING)) {
|
||||
if (mIsPowered && mWakefulness == WAKEFULNESS_DREAMING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1131,35 +1203,45 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
mWakeLockSummary |= WAKE_LOCK_CPU;
|
||||
break;
|
||||
case PowerManager.FULL_WAKE_LOCK:
|
||||
if (mWakefulness != WAKEFULNESS_ASLEEP) {
|
||||
if (mWakefulness == WAKEFULNESS_AWAKE
|
||||
|| mWakefulness == WAKEFULNESS_DREAMING) {
|
||||
mWakeLockSummary |= WAKE_LOCK_CPU
|
||||
| WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
|
||||
if (mWakefulness == WAKEFULNESS_AWAKE) {
|
||||
mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
|
||||
}
|
||||
}
|
||||
if (mWakefulness == WAKEFULNESS_AWAKE) {
|
||||
mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
|
||||
}
|
||||
break;
|
||||
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
|
||||
if (mWakefulness != WAKEFULNESS_ASLEEP) {
|
||||
if (mWakefulness == WAKEFULNESS_AWAKE
|
||||
|| mWakefulness == WAKEFULNESS_DREAMING) {
|
||||
mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT;
|
||||
if (mWakefulness == WAKEFULNESS_AWAKE) {
|
||||
mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
|
||||
}
|
||||
}
|
||||
if (mWakefulness == WAKEFULNESS_AWAKE) {
|
||||
mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
|
||||
}
|
||||
break;
|
||||
case PowerManager.SCREEN_DIM_WAKE_LOCK:
|
||||
if (mWakefulness != WAKEFULNESS_ASLEEP) {
|
||||
if (mWakefulness == WAKEFULNESS_AWAKE
|
||||
|| mWakefulness == WAKEFULNESS_DREAMING) {
|
||||
mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_DIM;
|
||||
if (mWakefulness == WAKEFULNESS_AWAKE) {
|
||||
mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
|
||||
}
|
||||
}
|
||||
if (mWakefulness == WAKEFULNESS_AWAKE) {
|
||||
mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
|
||||
}
|
||||
break;
|
||||
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
|
||||
if (mWakefulness != WAKEFULNESS_ASLEEP) {
|
||||
if (mWakefulness == WAKEFULNESS_AWAKE
|
||||
|| mWakefulness == WAKEFULNESS_DREAMING
|
||||
|| mWakefulness == WAKEFULNESS_DOZING) {
|
||||
mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
|
||||
}
|
||||
break;
|
||||
case PowerManager.DOZE_WAKE_LOCK:
|
||||
if (mWakefulness == WAKEFULNESS_DOZING) {
|
||||
mWakeLockSummary |= WAKE_LOCK_DOZE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1184,7 +1266,8 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
|
||||
|
||||
long nextTimeout = 0;
|
||||
if (mWakefulness != WAKEFULNESS_ASLEEP) {
|
||||
if (mWakefulness == WAKEFULNESS_AWAKE
|
||||
|| mWakefulness == WAKEFULNESS_DREAMING) {
|
||||
final int screenOffTimeout = getScreenOffTimeoutLocked();
|
||||
final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
|
||||
|
||||
@ -1205,8 +1288,7 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
|
||||
nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
|
||||
if (now < nextTimeout
|
||||
&& mDisplayPowerRequest.screenState
|
||||
!= DisplayPowerRequest.SCREEN_STATE_OFF) {
|
||||
&& mDisplayPowerRequest.wantScreenOnNormal()) {
|
||||
mUserActivitySummary = mDisplayPowerRequest.screenState
|
||||
== DisplayPowerRequest.SCREEN_STATE_BRIGHT ?
|
||||
USER_ACTIVITY_SCREEN_BRIGHT : USER_ACTIVITY_SCREEN_DIM;
|
||||
@ -1268,7 +1350,7 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
/**
|
||||
* Updates the wakefulness of the device.
|
||||
*
|
||||
* This is the function that decides whether the device should start napping
|
||||
* This is the function that decides whether the device should start dreaming
|
||||
* based on the current wake locks and user activity state. It may modify mDirty
|
||||
* if the wakefulness changes.
|
||||
*
|
||||
@ -1357,7 +1439,7 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the device enters or exits a napping or dreaming state.
|
||||
* Called when the device enters or exits a dreaming or dozing state.
|
||||
*
|
||||
* We do this asynchronously because we must call out of the power manager to start
|
||||
* the dream and we don't want to hold our lock while doing so. There is a risk that
|
||||
@ -1365,46 +1447,60 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
*/
|
||||
private void handleSandman() { // runs on handler thread
|
||||
// Handle preconditions.
|
||||
boolean startDreaming = false;
|
||||
final boolean startDreaming;
|
||||
final int wakefulness;
|
||||
synchronized (mLock) {
|
||||
mSandmanScheduled = false;
|
||||
boolean canDream = canDreamLocked();
|
||||
if (DEBUG_SPEW) {
|
||||
Slog.d(TAG, "handleSandman: canDream=" + canDream
|
||||
+ ", mWakefulness=" + wakefulnessToString(mWakefulness));
|
||||
}
|
||||
|
||||
if (canDream && mWakefulness == WAKEFULNESS_NAPPING) {
|
||||
startDreaming = true;
|
||||
wakefulness = mWakefulness;
|
||||
if (mSandmanSummoned) {
|
||||
startDreaming = ((wakefulness == WAKEFULNESS_DREAMING && canDreamLocked())
|
||||
|| wakefulness == WAKEFULNESS_DOZING);
|
||||
mSandmanSummoned = false;
|
||||
} else {
|
||||
startDreaming = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Start dreaming if needed.
|
||||
// We only control the dream on the handler thread, so we don't need to worry about
|
||||
// concurrent attempts to start or stop the dream.
|
||||
boolean isDreaming = false;
|
||||
final boolean isDreaming;
|
||||
if (mDreamManager != null) {
|
||||
// Restart the dream whenever the sandman is summoned.
|
||||
if (startDreaming) {
|
||||
mDreamManager.startDream();
|
||||
mDreamManager.stopDream();
|
||||
mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);
|
||||
}
|
||||
isDreaming = mDreamManager.isDreaming();
|
||||
} else {
|
||||
isDreaming = false;
|
||||
}
|
||||
|
||||
// Update dream state.
|
||||
// We might need to stop the dream again if the preconditions changed.
|
||||
boolean continueDreaming = false;
|
||||
synchronized (mLock) {
|
||||
if (isDreaming && canDreamLocked()) {
|
||||
if (mWakefulness == WAKEFULNESS_NAPPING) {
|
||||
mWakefulness = WAKEFULNESS_DREAMING;
|
||||
mDirty |= DIRTY_WAKEFULNESS;
|
||||
mBatteryLevelWhenDreamStarted = mBatteryLevel;
|
||||
updatePowerStateLocked();
|
||||
continueDreaming = true;
|
||||
} else if (mWakefulness == WAKEFULNESS_DREAMING) {
|
||||
if (!isBeingKeptAwakeLocked()
|
||||
// Remember the initial battery level when the dream started.
|
||||
if (startDreaming && isDreaming) {
|
||||
mBatteryLevelWhenDreamStarted = mBatteryLevel;
|
||||
if (wakefulness == WAKEFULNESS_DOZING) {
|
||||
Slog.i(TAG, "Dozing...");
|
||||
} else {
|
||||
Slog.i(TAG, "Dreaming...");
|
||||
}
|
||||
}
|
||||
|
||||
// If preconditions changed, wait for the next iteration to determine
|
||||
// whether the dream should continue (or be restarted).
|
||||
if (mSandmanSummoned || mWakefulness != wakefulness) {
|
||||
return; // wait for next cycle
|
||||
}
|
||||
|
||||
// Determine whether the dream should continue.
|
||||
if (wakefulness == WAKEFULNESS_DREAMING) {
|
||||
if (isDreaming && canDreamLocked()) {
|
||||
if (mDreamsBatteryLevelDrainCutoffConfig >= 0
|
||||
&& mBatteryLevel < mBatteryLevelWhenDreamStarted
|
||||
- DREAM_BATTERY_LEVEL_DRAIN_CUTOFF) {
|
||||
- mDreamsBatteryLevelDrainCutoffConfig
|
||||
&& !isBeingKeptAwakeLocked()) {
|
||||
// If the user activity timeout expired and the battery appears
|
||||
// to be draining faster than it is charging then stop dreaming
|
||||
// and go to sleep.
|
||||
@ -1414,53 +1510,64 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
+ mBatteryLevelWhenDreamStarted + "%. "
|
||||
+ "Battery level now: " + mBatteryLevel + "%.");
|
||||
} else {
|
||||
continueDreaming = true;
|
||||
return; // continue dreaming
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!continueDreaming) {
|
||||
handleDreamFinishedLocked();
|
||||
|
||||
// Dream has ended or will be stopped. Update the power state.
|
||||
if (isItBedTimeYetLocked()) {
|
||||
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
|
||||
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
|
||||
updatePowerStateLocked();
|
||||
} else {
|
||||
wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
|
||||
updatePowerStateLocked();
|
||||
}
|
||||
} else if (wakefulness == WAKEFULNESS_DOZING) {
|
||||
if (isDreaming) {
|
||||
return; // continue dozing
|
||||
}
|
||||
|
||||
// Doze has ended or will be stopped. Update the power state.
|
||||
reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis());
|
||||
updatePowerStateLocked();
|
||||
}
|
||||
}
|
||||
|
||||
// Stop dreaming if needed.
|
||||
// It's possible that something else changed to make us need to start the dream again.
|
||||
// If so, then the power manager will have posted another message to the handler
|
||||
// to take care of it later.
|
||||
if (mDreamManager != null) {
|
||||
if (!continueDreaming) {
|
||||
mDreamManager.stopDream();
|
||||
}
|
||||
// Stop dream.
|
||||
if (isDreaming) {
|
||||
mDreamManager.stopDream();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the device is allowed to dream in its current state
|
||||
* assuming that it is currently napping or dreaming.
|
||||
* Returns true if the device is allowed to dream in its current state.
|
||||
* This function is not called when dozing.
|
||||
*/
|
||||
private boolean canDreamLocked() {
|
||||
return mDreamsSupportedConfig
|
||||
&& mDreamsEnabledSetting
|
||||
&& mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF
|
||||
&& mBootCompleted
|
||||
&& (mIsPowered || isBeingKeptAwakeLocked());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a dream is ending to figure out what to do next.
|
||||
*/
|
||||
private void handleDreamFinishedLocked() {
|
||||
if (mWakefulness == WAKEFULNESS_NAPPING
|
||||
|| mWakefulness == WAKEFULNESS_DREAMING) {
|
||||
if (isItBedTimeYetLocked()) {
|
||||
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
|
||||
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
|
||||
updatePowerStateLocked();
|
||||
} else {
|
||||
wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
|
||||
updatePowerStateLocked();
|
||||
if (mWakefulness != WAKEFULNESS_DREAMING
|
||||
|| !mDreamsSupportedConfig
|
||||
|| !mDreamsEnabledSetting
|
||||
|| !mDisplayPowerRequest.wantScreenOnNormal()
|
||||
|| !mBootCompleted) {
|
||||
return false;
|
||||
}
|
||||
if (!isBeingKeptAwakeLocked()) {
|
||||
if (!mIsPowered && !mDreamsEnabledByDefaultConfig) {
|
||||
return false;
|
||||
}
|
||||
if (!mIsPowered
|
||||
&& mDreamsBatteryLevelMinimumWhenNotPoweredConfig >= 0
|
||||
&& mBatteryLevel < mDreamsBatteryLevelMinimumWhenNotPoweredConfig) {
|
||||
return false;
|
||||
}
|
||||
if (mIsPowered
|
||||
&& mDreamsBatteryLevelMinimumWhenPoweredConfig >= 0
|
||||
&& mBatteryLevel < mDreamsBatteryLevelMinimumWhenPoweredConfig) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleScreenOnBlockerReleased() {
|
||||
@ -1482,11 +1589,11 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
|
||||
| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
|
||||
| DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {
|
||||
int newScreenState = getDesiredScreenPowerStateLocked();
|
||||
final int newScreenState = getDesiredScreenPowerStateLocked();
|
||||
if (newScreenState != mDisplayPowerRequest.screenState) {
|
||||
mDisplayPowerRequest.screenState = newScreenState;
|
||||
nativeSetPowerState(
|
||||
newScreenState != DisplayPowerRequest.SCREEN_STATE_OFF,
|
||||
mDisplayPowerRequest.wantScreenOnNormal(),
|
||||
newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT);
|
||||
}
|
||||
|
||||
@ -1555,6 +1662,10 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
return DisplayPowerRequest.SCREEN_STATE_OFF;
|
||||
}
|
||||
|
||||
if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
|
||||
return DisplayPowerRequest.SCREEN_STATE_DOZE;
|
||||
}
|
||||
|
||||
if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
|
||||
|| (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
|
||||
|| !mBootCompleted) {
|
||||
@ -1606,7 +1717,18 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
*/
|
||||
private void updateSuspendBlockerLocked() {
|
||||
final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
|
||||
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker();
|
||||
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
|
||||
final boolean autoSuspend = !needDisplaySuspendBlocker;
|
||||
|
||||
// Disable auto-suspend if needed.
|
||||
if (!autoSuspend) {
|
||||
if (mDecoupleAutoSuspendModeFromDisplayConfig) {
|
||||
setAutoSuspendModeLocked(false);
|
||||
}
|
||||
if (mDecoupleInteractiveModeFromDisplayConfig) {
|
||||
setInteractiveModeLocked(true);
|
||||
}
|
||||
}
|
||||
|
||||
// First acquire suspend blockers if needed.
|
||||
if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
|
||||
@ -1627,17 +1749,27 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
mDisplaySuspendBlocker.release();
|
||||
mHoldingDisplaySuspendBlocker = false;
|
||||
}
|
||||
|
||||
// Enable auto-suspend if needed.
|
||||
if (autoSuspend) {
|
||||
if (mDecoupleInteractiveModeFromDisplayConfig) {
|
||||
setInteractiveModeLocked(false);
|
||||
}
|
||||
if (mDecoupleAutoSuspendModeFromDisplayConfig) {
|
||||
setAutoSuspendModeLocked(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we must keep a suspend blocker active on behalf of the display.
|
||||
* We do so if the screen is on or is in transition between states.
|
||||
*/
|
||||
private boolean needDisplaySuspendBlocker() {
|
||||
private boolean needDisplaySuspendBlockerLocked() {
|
||||
if (!mDisplayReady) {
|
||||
return true;
|
||||
}
|
||||
if (mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
|
||||
if (mDisplayPowerRequest.wantScreenOnNormal()) {
|
||||
// If we asked for the screen to be on but it is off due to the proximity
|
||||
// sensor then we may suspend but only if the configuration allows it.
|
||||
// On some hardware it may not be safe to suspend because the proximity
|
||||
@ -1647,13 +1779,34 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Let the system suspend if the screen is off or dozing.
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setAutoSuspendModeLocked(boolean enable) {
|
||||
if (enable != mAutoSuspendModeEnabled) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Setting auto-suspend mode to " + enable);
|
||||
}
|
||||
mAutoSuspendModeEnabled = enable;
|
||||
nativeSetAutoSuspend(enable);
|
||||
}
|
||||
}
|
||||
|
||||
private void setInteractiveModeLocked(boolean enable) {
|
||||
if (enable != mInteractiveModeEnabled) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Setting interactive mode to " + enable);
|
||||
}
|
||||
mInteractiveModeEnabled = enable;
|
||||
nativeSetInteractive(enable);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isScreenOnInternal() {
|
||||
synchronized (mLock) {
|
||||
return !mSystemReady
|
||||
|| mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF;
|
||||
|| mDisplayPowerRequest.wantScreenOnNormal();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1887,10 +2040,13 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
pw.println(" mProximityPositive=" + mProximityPositive);
|
||||
pw.println(" mBootCompleted=" + mBootCompleted);
|
||||
pw.println(" mSystemReady=" + mSystemReady);
|
||||
pw.println(" mAutoSuspendModeEnabled=" + mAutoSuspendModeEnabled);
|
||||
pw.println(" mInteactiveModeEnabled=" + mInteractiveModeEnabled);
|
||||
pw.println(" mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
|
||||
pw.println(" mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary));
|
||||
pw.println(" mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
|
||||
pw.println(" mSandmanScheduled=" + mSandmanScheduled);
|
||||
pw.println(" mSandmanSummoned=" + mSandmanSummoned);
|
||||
pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
|
||||
pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
|
||||
pw.println(" mSendWakeUpFinishedNotificationWhenReady="
|
||||
@ -1906,6 +2062,10 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
|
||||
pw.println();
|
||||
pw.println("Settings and Configuration:");
|
||||
pw.println(" mDecoupleAutoSuspendModeFromDisplayConfig="
|
||||
+ mDecoupleAutoSuspendModeFromDisplayConfig);
|
||||
pw.println(" mDecoupleInteractiveModeFromDisplayConfig="
|
||||
+ mDecoupleInteractiveModeFromDisplayConfig);
|
||||
pw.println(" mWakeUpWhenPluggedOrUnpluggedConfig="
|
||||
+ mWakeUpWhenPluggedOrUnpluggedConfig);
|
||||
pw.println(" mSuspendWhenScreenOffDueToProximityConfig="
|
||||
@ -1916,6 +2076,14 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
+ mDreamsActivatedOnSleepByDefaultConfig);
|
||||
pw.println(" mDreamsActivatedOnDockByDefaultConfig="
|
||||
+ mDreamsActivatedOnDockByDefaultConfig);
|
||||
pw.println(" mDreamsEnabledOnBatteryConfig="
|
||||
+ mDreamsEnabledOnBatteryConfig);
|
||||
pw.println(" mDreamsBatteryLevelMinimumWhenPoweredConfig="
|
||||
+ mDreamsBatteryLevelMinimumWhenPoweredConfig);
|
||||
pw.println(" mDreamsBatteryLevelMinimumWhenNotPoweredConfig="
|
||||
+ mDreamsBatteryLevelMinimumWhenNotPoweredConfig);
|
||||
pw.println(" mDreamsBatteryLevelDrainCutoffConfig="
|
||||
+ mDreamsBatteryLevelDrainCutoffConfig);
|
||||
pw.println(" mDreamsEnabledSetting=" + mDreamsEnabledSetting);
|
||||
pw.println(" mDreamsActivateOnSleepSetting=" + mDreamsActivateOnSleepSetting);
|
||||
pw.println(" mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting);
|
||||
@ -1991,8 +2159,8 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
return "Awake";
|
||||
case WAKEFULNESS_DREAMING:
|
||||
return "Dreaming";
|
||||
case WAKEFULNESS_NAPPING:
|
||||
return "Napping";
|
||||
case WAKEFULNESS_DOZING:
|
||||
return "Dozing";
|
||||
default:
|
||||
return Integer.toString(wakefulness);
|
||||
}
|
||||
@ -2169,6 +2337,7 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
+ " (uid=" + mOwnerUid + ", pid=" + mOwnerPid + ", ws=" + mWorkSource + ")";
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private String getLockLevelString() {
|
||||
switch (mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
|
||||
case PowerManager.FULL_WAKE_LOCK:
|
||||
@ -2181,6 +2350,8 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
return "PARTIAL_WAKE_LOCK ";
|
||||
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
|
||||
return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
|
||||
case PowerManager.DOZE_WAKE_LOCK:
|
||||
return "DOZE_WAKE_LOCK ";
|
||||
default:
|
||||
return "??? ";
|
||||
}
|
||||
@ -2311,16 +2482,24 @@ public final class PowerManagerService extends com.android.server.SystemService
|
||||
synchronized (this) {
|
||||
mBlanked = true;
|
||||
mDisplayManagerInternal.blankAllDisplaysFromPowerManager();
|
||||
nativeSetInteractive(false);
|
||||
nativeSetAutoSuspend(true);
|
||||
if (!mDecoupleInteractiveModeFromDisplayConfig) {
|
||||
setInteractiveModeLocked(false);
|
||||
}
|
||||
if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
|
||||
setAutoSuspendModeLocked(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unblankAllDisplays() {
|
||||
synchronized (this) {
|
||||
nativeSetAutoSuspend(false);
|
||||
nativeSetInteractive(true);
|
||||
if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
|
||||
setAutoSuspendModeLocked(false);
|
||||
}
|
||||
if (!mDecoupleInteractiveModeFromDisplayConfig) {
|
||||
setInteractiveModeLocked(true);
|
||||
}
|
||||
mDisplayManagerInternal.unblankAllDisplaysFromPowerManager();
|
||||
mBlanked = false;
|
||||
}
|
||||
|
@ -364,8 +364,8 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
|
||||
* motion event processing when the screen is off since these events are normally
|
||||
* dropped. */
|
||||
@Override
|
||||
public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
|
||||
return mService.mPolicy.interceptMotionBeforeQueueingWhenScreenOff(policyFlags);
|
||||
public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) {
|
||||
return mService.mPolicy.interceptMotionBeforeQueueingWhenScreenOff(whenNanos, policyFlags);
|
||||
}
|
||||
|
||||
/* Provides an opportunity for the window manager policy to process a key before
|
||||
|
@ -8,6 +8,7 @@ LOCAL_SRC_FILES += \
|
||||
$(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_dreams_McuHal.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \
|
||||
$(LOCAL_REL_DIR)/com_android_server_input_InputWindowHandle.cpp \
|
||||
|
100
services/core/jni/com_android_server_dreams_McuHal.cpp
Normal file
100
services/core/jni/com_android_server_dreams_McuHal.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "McuHal"
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include "JNIHelp.h"
|
||||
#include "jni.h"
|
||||
|
||||
#include <ScopedUtfChars.h>
|
||||
#include <ScopedPrimitiveArray.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Log.h>
|
||||
#include <hardware/mcu.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
static jlong nativeOpen(JNIEnv* env, jclass clazz) {
|
||||
mcu_module_t* module = NULL;
|
||||
status_t err = hw_get_module(MCU_HARDWARE_MODULE_ID,
|
||||
(hw_module_t const**)&module);
|
||||
if (err) {
|
||||
ALOGE("Couldn't load %s module (%s)", MCU_HARDWARE_MODULE_ID, strerror(-err));
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = module->init(module);
|
||||
if (err) {
|
||||
ALOGE("Couldn't initialize %s module (%s)", MCU_HARDWARE_MODULE_ID, strerror(-err));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<jlong>(module);
|
||||
}
|
||||
|
||||
static jbyteArray nativeSendMessage(JNIEnv* env, jclass clazz,
|
||||
jlong ptr, jstring msgStr, jbyteArray argArray) {
|
||||
mcu_module_t* module = reinterpret_cast<mcu_module_t*>(ptr);
|
||||
|
||||
ScopedUtfChars msg(env, msgStr);
|
||||
ALOGV("Sending message %s to MCU", msg.c_str());
|
||||
|
||||
void* result = NULL;
|
||||
size_t resultSize = 0;
|
||||
status_t err;
|
||||
if (argArray) {
|
||||
ScopedByteArrayRO arg(env, argArray);
|
||||
err = module->sendMessage(module, msg.c_str(), arg.get(), arg.size(),
|
||||
&result, &resultSize);
|
||||
} else {
|
||||
err = module->sendMessage(module, msg.c_str(), NULL, 0, &result, &resultSize);
|
||||
}
|
||||
if (err) {
|
||||
ALOGE("Couldn't send message to MCU (%s)", strerror(-err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jbyteArray resultArray = env->NewByteArray(resultSize);
|
||||
if (resultArray) {
|
||||
env->SetByteArrayRegion(resultArray, 0, resultSize, static_cast<jbyte*>(result));
|
||||
}
|
||||
free(result);
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
static JNINativeMethod gMcuHalMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "nativeOpen", "()J",
|
||||
(void*) nativeOpen },
|
||||
{ "nativeSendMessage", "(JLjava/lang/String;[B)[B",
|
||||
(void*) nativeSendMessage },
|
||||
};
|
||||
|
||||
int register_android_server_dreams_McuHal(JNIEnv* env) {
|
||||
int res = jniRegisterNativeMethods(env, "com/android/server/dreams/McuHal",
|
||||
gMcuHalMethods, NELEM(gMcuHalMethods));
|
||||
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} /* namespace android */
|
@ -151,8 +151,6 @@ static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t styl
|
||||
|
||||
enum {
|
||||
WM_ACTION_PASS_TO_USER = 1,
|
||||
WM_ACTION_WAKE_UP = 2,
|
||||
WM_ACTION_GO_TO_SLEEP = 4,
|
||||
};
|
||||
|
||||
|
||||
@ -844,7 +842,7 @@ void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& p
|
||||
JNIEnv* env = jniEnv();
|
||||
jint wmActions = env->CallIntMethod(mServiceObj,
|
||||
gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
|
||||
policyFlags);
|
||||
when, policyFlags);
|
||||
if (checkAndClearExceptionFromCallback(env,
|
||||
"interceptMotionBeforeQueueingWhenScreenOff")) {
|
||||
wmActions = 0;
|
||||
@ -860,20 +858,6 @@ void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& p
|
||||
|
||||
void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
|
||||
uint32_t& policyFlags) {
|
||||
if (wmActions & WM_ACTION_GO_TO_SLEEP) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
ALOGD("handleInterceptActions: Going to sleep.");
|
||||
#endif
|
||||
android_server_PowerManagerService_goToSleep(when);
|
||||
}
|
||||
|
||||
if (wmActions & WM_ACTION_WAKE_UP) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
ALOGD("handleInterceptActions: Waking up.");
|
||||
#endif
|
||||
android_server_PowerManagerService_wakeUp(when);
|
||||
}
|
||||
|
||||
if (wmActions & WM_ACTION_PASS_TO_USER) {
|
||||
policyFlags |= POLICY_FLAG_PASS_TO_USER;
|
||||
} else {
|
||||
@ -1412,7 +1396,7 @@ int register_android_server_InputManager(JNIEnv* env) {
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
|
||||
clazz,
|
||||
"interceptMotionBeforeQueueingWhenScreenOff", "(I)I");
|
||||
"interceptMotionBeforeQueueingWhenScreenOff", "(JI)I");
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
|
||||
"interceptKeyBeforeDispatching",
|
||||
|
@ -36,6 +36,7 @@ int register_android_server_location_GpsLocationProvider(JNIEnv* env);
|
||||
int register_android_server_location_FlpHardwareProvider(JNIEnv* env);
|
||||
int register_android_server_connectivity_Vpn(JNIEnv* env);
|
||||
int register_android_server_AssetAtlasService(JNIEnv* env);
|
||||
int register_android_server_dreams_McuHal(JNIEnv* env);
|
||||
};
|
||||
|
||||
using namespace android;
|
||||
@ -67,7 +68,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
register_android_server_connectivity_Vpn(env);
|
||||
register_android_server_AssetAtlasService(env);
|
||||
register_android_server_ConsumerIrService(env);
|
||||
|
||||
register_android_server_dreams_McuHal(env);
|
||||
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
14
tests/DozeTest/Android.mk
Normal file
14
tests/DozeTest/Android.mk
Normal file
@ -0,0 +1,14 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
# Only compile source java files in this apk.
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := DozeTest
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
# Use the following include to make our test apk.
|
||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
35
tests/DozeTest/AndroidManifest.xml
Normal file
35
tests/DozeTest/AndroidManifest.xml
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 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.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.dreams.dozetest">
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<application android:label="@string/app_name">
|
||||
<service
|
||||
android:name="DozeTestDream"
|
||||
android:exported="true"
|
||||
android:icon="@drawable/ic_app"
|
||||
android:label="@string/doze_dream_name">
|
||||
<!-- Commented out to prevent this dream from appearing in the list of
|
||||
dreams that the user can select via the Settings application.
|
||||
<intent-filter>
|
||||
<action android:name="android.service.dreams.DreamService" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
-->
|
||||
</service>
|
||||
</application>
|
||||
</manifest>
|
BIN
tests/DozeTest/res/drawable-hdpi/ic_app.png
Executable file
BIN
tests/DozeTest/res/drawable-hdpi/ic_app.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
BIN
tests/DozeTest/res/drawable-mdpi/ic_app.png
Normal file
BIN
tests/DozeTest/res/drawable-mdpi/ic_app.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
41
tests/DozeTest/res/layout/dream.xml
Normal file
41
tests/DozeTest/res/layout/dream.xml
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 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.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/alarm_clock_label" />
|
||||
<TextView android:id="@+id/alarm_clock"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="32dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/tick_clock_label" />
|
||||
<TextClock android:id="@+id/tick_clock"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
25
tests/DozeTest/res/values/strings.xml
Normal file
25
tests/DozeTest/res/values/strings.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 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.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Name of the package of basic screensavers, shown in Settings > Apps. [CHAR LIMIT=40] -->
|
||||
<string name="app_name">Doze Test</string>
|
||||
|
||||
<!-- Name of the screensaver. [CHAR LIMIT=40] -->
|
||||
<string name="doze_dream_name">Doze Test</string>
|
||||
|
||||
<string name="alarm_clock_label">This clock is updated using the Alarm Manager</string>
|
||||
<string name="tick_clock_label">This clock is updated using TIME_TICK Broadcasts</string>
|
||||
</resources>
|
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.dreams.dozetest;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.PowerManager;
|
||||
import android.service.dreams.DozeHardware;
|
||||
import android.service.dreams.DreamService;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Simple test for doze mode.
|
||||
* <p>
|
||||
* adb shell setprop debug.doze.component com.android.dreams.dozetest/.DozeTestDream
|
||||
* </p>
|
||||
*/
|
||||
public class DozeTestDream extends DreamService {
|
||||
private static final String TAG = DozeTestDream.class.getSimpleName();
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
// Amount of time to allow to update the time shown on the screen before releasing
|
||||
// the wakelock. This timeout is design to compensate for the fact that we don't
|
||||
// currently have a way to know when time display contents have actually been
|
||||
// refreshed once the dream has finished rendering a new frame.
|
||||
private static final int UPDATE_TIME_TIMEOUT = 100;
|
||||
|
||||
// A doze hardware message string we use for end-to-end testing.
|
||||
// Doesn't mean anything. Real hardware won't handle it.
|
||||
private static final String TEST_PING_MESSAGE = "test.ping";
|
||||
|
||||
private PowerManager mPowerManager;
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
private AlarmManager mAlarmManager;
|
||||
private PendingIntent mAlarmIntent;
|
||||
|
||||
private TextView mAlarmClock;
|
||||
|
||||
private final Date mTime = new Date();
|
||||
private java.text.DateFormat mTimeFormat;
|
||||
|
||||
private boolean mDreaming;
|
||||
private DozeHardware mDozeHardware;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
mPowerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
||||
|
||||
mAlarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
Intent intent = new Intent("com.android.dreams.dozetest.ACTION_ALARM");
|
||||
intent.setPackage(getPackageName());
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(intent.getAction());
|
||||
registerReceiver(mAlarmReceiver, filter);
|
||||
mAlarmIntent = PendingIntent.getBroadcast(this, 0, intent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
unregisterReceiver(mAlarmReceiver);
|
||||
mAlarmIntent.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
setInteractive(false);
|
||||
setLowProfile(true);
|
||||
setFullscreen(true);
|
||||
setContentView(R.layout.dream);
|
||||
|
||||
mAlarmClock = (TextView)findViewById(R.id.alarm_clock);
|
||||
|
||||
mTimeFormat = DateFormat.getTimeFormat(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDreamingStarted() {
|
||||
super.onDreamingStarted();
|
||||
|
||||
mDreaming = true;
|
||||
mDozeHardware = getDozeHardware();
|
||||
|
||||
Log.d(TAG, "Dream started: canDoze=" + canDoze()
|
||||
+ ", dozeHardware=" + mDozeHardware);
|
||||
|
||||
performTimeUpdate();
|
||||
|
||||
if (mDozeHardware != null) {
|
||||
mDozeHardware.sendMessage(TEST_PING_MESSAGE, null);
|
||||
mDozeHardware.setEnableMcu(true);
|
||||
}
|
||||
startDozing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDreamingStopped() {
|
||||
super.onDreamingStopped();
|
||||
|
||||
mDreaming = false;
|
||||
if (mDozeHardware != null) {
|
||||
mDozeHardware.setEnableMcu(false);
|
||||
mDozeHardware = null;
|
||||
}
|
||||
|
||||
Log.d(TAG, "Dream ended: isDozing=" + isDozing());
|
||||
|
||||
stopDozing();
|
||||
cancelTimeUpdate();
|
||||
}
|
||||
|
||||
private void performTimeUpdate() {
|
||||
if (mDreaming) {
|
||||
long now = System.currentTimeMillis();
|
||||
now -= now % 60000; // back up to last minute boundary
|
||||
|
||||
mTime.setTime(now);
|
||||
mAlarmClock.setText(mTimeFormat.format(mTime));
|
||||
|
||||
mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, now + 60000, mAlarmIntent);
|
||||
|
||||
mWakeLock.acquire(UPDATE_TIME_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelTimeUpdate() {
|
||||
mAlarmManager.cancel(mAlarmIntent);
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mAlarmReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
performTimeUpdate();
|
||||
}
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user