Fix wake lock logic during Dream startup
Fixes a crash that would happen in all dreams that did not have permission to acquire wake locks. Instead moves the wake lock logic into the system process. Also fixes a bug in DozeService where the wake lock was not held until dozing was actually properly initialized. Fixes: 31612287 Bug: 31044352 Related-CL: I85955a2b7d6bad5171accbc336117a9660b1b198 Test: adb shell settings put secure screensaver_components com.android.dreams.basic/.Colors; adb shell service call dreams 1 Change-Id: Idb3f921ee71b6da6c2ab0c44c332ef91f93ddbc0
This commit is contained in:
@@ -27,6 +27,7 @@ import android.graphics.PixelFormat;
|
|||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.IRemoteCallback;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
@@ -192,9 +193,6 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
|
|
||||||
private boolean mDebug = false;
|
private boolean mDebug = false;
|
||||||
|
|
||||||
private PowerManager.WakeLock mWakeLock;
|
|
||||||
private boolean mWakeLockAcquired;
|
|
||||||
|
|
||||||
public DreamService() {
|
public DreamService() {
|
||||||
mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
|
mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
|
||||||
}
|
}
|
||||||
@@ -789,8 +787,6 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
if (mDebug) Slog.v(TAG, "onCreate()");
|
if (mDebug) Slog.v(TAG, "onCreate()");
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
mWakeLock = getSystemService(PowerManager.class)
|
|
||||||
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DreamService");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -830,21 +826,9 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
@Override
|
@Override
|
||||||
public final IBinder onBind(Intent intent) {
|
public final IBinder onBind(Intent intent) {
|
||||||
if (mDebug) Slog.v(TAG, "onBind() intent = " + intent);
|
if (mDebug) Slog.v(TAG, "onBind() intent = " + intent);
|
||||||
|
|
||||||
// Need to stay awake until we dispatch onDreamingStarted. This is released either in
|
|
||||||
// attach() or onDestroy().
|
|
||||||
mWakeLock.acquire(5000);
|
|
||||||
mWakeLockAcquired = true;
|
|
||||||
return new DreamServiceWrapper();
|
return new DreamServiceWrapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void releaseWakeLockIfNeeded() {
|
|
||||||
if (mWakeLockAcquired) {
|
|
||||||
mWakeLock.release();
|
|
||||||
mWakeLockAcquired = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the dream and detaches from the window.
|
* Stops the dream and detaches from the window.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -921,8 +905,6 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
detach();
|
detach();
|
||||||
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
|
||||||
releaseWakeLockIfNeeded(); // for acquire in onBind()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// end public api
|
// end public api
|
||||||
@@ -961,9 +943,9 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
* Must run on mHandler.
|
* Must run on mHandler.
|
||||||
*
|
*
|
||||||
* @param windowToken A window token that will allow a window to be created in the correct layer.
|
* @param windowToken A window token that will allow a window to be created in the correct layer.
|
||||||
|
* @param started A callback that will be invoked once onDreamingStarted has completed.
|
||||||
*/
|
*/
|
||||||
private final void attach(IBinder windowToken, boolean canDoze) {
|
private final void attach(IBinder windowToken, boolean canDoze, IRemoteCallback started) {
|
||||||
try {
|
|
||||||
if (mWindowToken != null) {
|
if (mWindowToken != null) {
|
||||||
Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
|
Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
|
||||||
return;
|
return;
|
||||||
@@ -990,16 +972,14 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
|
mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
|
||||||
mWindow.setFormat(PixelFormat.OPAQUE);
|
mWindow.setFormat(PixelFormat.OPAQUE);
|
||||||
|
|
||||||
if (mDebug) {
|
if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
|
||||||
Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
|
|
||||||
windowToken, WindowManager.LayoutParams.TYPE_DREAM));
|
windowToken, WindowManager.LayoutParams.TYPE_DREAM));
|
||||||
}
|
|
||||||
|
|
||||||
WindowManager.LayoutParams lp = mWindow.getAttributes();
|
WindowManager.LayoutParams lp = mWindow.getAttributes();
|
||||||
lp.type = WindowManager.LayoutParams.TYPE_DREAM;
|
lp.type = WindowManager.LayoutParams.TYPE_DREAM;
|
||||||
lp.token = windowToken;
|
lp.token = windowToken;
|
||||||
lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
|
lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
|
||||||
lp.flags |= (WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
lp.flags |= ( WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
||||||
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
|
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
|
||||||
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
|
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
|
||||||
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|
||||||
@@ -1033,19 +1013,25 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
// which is posted to the handler by addView, so we post onDreamingStarted
|
// which is posted to the handler by addView, so we post onDreamingStarted
|
||||||
// to the handler also. Need to watch out here in case detach occurs before
|
// to the handler also. Need to watch out here in case detach occurs before
|
||||||
// this callback is invoked.
|
// this callback is invoked.
|
||||||
mHandler.post(mWakeLock.wrap(() -> {
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
if (mWindow != null || mWindowless) {
|
if (mWindow != null || mWindowless) {
|
||||||
if (mDebug) {
|
if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
|
||||||
Slog.v(TAG, "Calling onDreamingStarted()");
|
|
||||||
}
|
|
||||||
mStarted = true;
|
mStarted = true;
|
||||||
|
try {
|
||||||
onDreamingStarted();
|
onDreamingStarted();
|
||||||
}
|
|
||||||
}));
|
|
||||||
} finally {
|
} finally {
|
||||||
releaseWakeLockIfNeeded(); // for acquire in onBind
|
try {
|
||||||
|
started.sendResult(null);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private boolean getWindowFlagValue(int flag, boolean defaultValue) {
|
private boolean getWindowFlagValue(int flag, boolean defaultValue) {
|
||||||
return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
|
return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
|
||||||
@@ -1116,11 +1102,12 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
|
|
||||||
private final class DreamServiceWrapper extends IDreamService.Stub {
|
private final class DreamServiceWrapper extends IDreamService.Stub {
|
||||||
@Override
|
@Override
|
||||||
public void attach(final IBinder windowToken, final boolean canDoze) {
|
public void attach(final IBinder windowToken, final boolean canDoze,
|
||||||
|
IRemoteCallback started) {
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DreamService.this.attach(windowToken, canDoze);
|
DreamService.this.attach(windowToken, canDoze, started);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,13 @@
|
|||||||
|
|
||||||
package android.service.dreams;
|
package android.service.dreams;
|
||||||
|
|
||||||
|
import android.os.IRemoteCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
oneway interface IDreamService {
|
oneway interface IDreamService {
|
||||||
void attach(IBinder windowToken, boolean canDoze);
|
void attach(IBinder windowToken, boolean canDoze, IRemoteCallback started);
|
||||||
void detach();
|
void detach();
|
||||||
void wakeUp();
|
void wakeUp();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,9 +159,7 @@ public class DozeService extends DreamService {
|
|||||||
// Ask the host to get things ready to start dozing.
|
// Ask the host to get things ready to start dozing.
|
||||||
// Once ready, we call startDozing() at which point the CPU may suspend
|
// Once ready, we call startDozing() at which point the CPU may suspend
|
||||||
// and we will need to acquire a wakelock to do work.
|
// and we will need to acquire a wakelock to do work.
|
||||||
mHost.startDozing(new Runnable() {
|
mHost.startDozing(mWakeLock.wrap(() -> {
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (mDreaming) {
|
if (mDreaming) {
|
||||||
startDozing();
|
startDozing();
|
||||||
|
|
||||||
@@ -169,8 +167,7 @@ public class DozeService extends DreamService {
|
|||||||
// wakelock whenever we are doing work. Note that we never call
|
// wakelock whenever we are doing work. Note that we never call
|
||||||
// stopDozing because can we just keep dozing until the bitter end.
|
// stopDozing because can we just keep dozing until the bitter end.
|
||||||
}
|
}
|
||||||
}
|
}));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -24,8 +24,10 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.IRemoteCallback;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.IBinder.DeathRecipient;
|
import android.os.IBinder.DeathRecipient;
|
||||||
@@ -253,7 +255,8 @@ final class DreamController {
|
|||||||
private void attach(IDreamService service) {
|
private void attach(IDreamService service) {
|
||||||
try {
|
try {
|
||||||
service.asBinder().linkToDeath(mCurrentDream, 0);
|
service.asBinder().linkToDeath(mCurrentDream, 0);
|
||||||
service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze);
|
service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze,
|
||||||
|
mCurrentDream.mDreamingStartedCallback);
|
||||||
} catch (RemoteException ex) {
|
} catch (RemoteException ex) {
|
||||||
Slog.e(TAG, "The dream service died unexpectedly.", ex);
|
Slog.e(TAG, "The dream service died unexpectedly.", ex);
|
||||||
stopDream(true /*immediate*/);
|
stopDream(true /*immediate*/);
|
||||||
@@ -298,10 +301,10 @@ final class DreamController {
|
|||||||
mCanDoze = canDoze;
|
mCanDoze = canDoze;
|
||||||
mUserId = userId;
|
mUserId = userId;
|
||||||
mWakeLock = wakeLock;
|
mWakeLock = wakeLock;
|
||||||
// Hold the lock while we're waiting for the service to connect. Released either when
|
// Hold the lock while we're waiting for the service to connect and start dreaming.
|
||||||
// DreamService connects (and is then responsible for keeping the device awake) or
|
// Released after the service has started dreaming, we stop dreaming, or it timed out.
|
||||||
// dreaming stops.
|
|
||||||
mWakeLock.acquire();
|
mWakeLock.acquire();
|
||||||
|
mHandler.postDelayed(mReleaseWakeLockIfNeeded, 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// May be called on any thread.
|
// May be called on any thread.
|
||||||
@@ -324,25 +327,17 @@ final class DreamController {
|
|||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
|
||||||
mConnected = true;
|
mConnected = true;
|
||||||
if (mCurrentDream == DreamRecord.this && mService == null) {
|
if (mCurrentDream == DreamRecord.this && mService == null) {
|
||||||
attach(IDreamService.Stub.asInterface(service));
|
attach(IDreamService.Stub.asInterface(service));
|
||||||
}
|
// Wake lock will be released once dreaming starts.
|
||||||
} finally {
|
} else {
|
||||||
releaseWakeLockIfNeeded();
|
releaseWakeLockIfNeeded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void releaseWakeLockIfNeeded() {
|
|
||||||
if (mWakeLock != null) {
|
|
||||||
mWakeLock.release();
|
|
||||||
mWakeLock = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// May be called on any thread.
|
// May be called on any thread.
|
||||||
@Override
|
@Override
|
||||||
public void onServiceDisconnected(ComponentName name) {
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
@@ -356,5 +351,23 @@ final class DreamController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void releaseWakeLockIfNeeded() {
|
||||||
|
if (mWakeLock != null) {
|
||||||
|
mWakeLock.release();
|
||||||
|
mWakeLock = null;
|
||||||
|
mHandler.removeCallbacks(mReleaseWakeLockIfNeeded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Runnable mReleaseWakeLockIfNeeded = this::releaseWakeLockIfNeeded;
|
||||||
|
|
||||||
|
final IRemoteCallback mDreamingStartedCallback = new IRemoteCallback.Stub() {
|
||||||
|
// May be called on any thread.
|
||||||
|
@Override
|
||||||
|
public void sendResult(Bundle data) throws RemoteException {
|
||||||
|
mHandler.post(mReleaseWakeLockIfNeeded);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user