From a8e46412963a1ba466d1a1f180eef703d262e008 Mon Sep 17 00:00:00 2001
From: Galia Peycheva
Date: Fri, 14 Feb 2020 19:00:29 +0100
Subject: Clean up dreamland
Sort imports and exchange inline Runnables for lambdas
Bug: 133216167
Test: m && ./vendor/google/tools/flashall
Merged-In: Ife3d13904a698efbe0933676b176ac1fbb53d0bd
Change-Id: Ife3d13904a698efbe0933676b176ac1fbb53d0bd
(cherry picked from commit 21cab31b8260163ae9a14b9a9083703175767646)
---
core/java/android/service/dreams/DreamService.java | 21 +------
.../com/android/server/dreams/DreamController.java | 68 ++++++++--------------
2 files changed, 28 insertions(+), 61 deletions(-)
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index de4a5511fcdb..96a89bcd0120 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -1160,32 +1160,17 @@ public class DreamService extends Service implements Window.Callback {
@Override
public void attach(final IBinder windowToken, final boolean canDoze,
IRemoteCallback started) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- DreamService.this.attach(windowToken, canDoze, started);
- }
- });
+ mHandler.post(() -> DreamService.this.attach(windowToken, canDoze, started));
}
@Override
public void detach() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- DreamService.this.detach();
- }
- });
+ mHandler.post(DreamService.this::detach);
}
@Override
public void wakeUp() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- DreamService.this.wakeUp(true /*fromSystem*/);
- }
- });
+ mHandler.post(() -> DreamService.this.wakeUp(true /*fromSystem*/));
}
}
}
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index fbad8dede87d..2ed4f390c973 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -16,8 +16,8 @@
package com.android.server.dreams;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import android.content.ComponentName;
import android.content.Context;
@@ -27,10 +27,10 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
import android.os.IRemoteCallback;
import android.os.PowerManager;
import android.os.RemoteException;
-import android.os.IBinder.DeathRecipient;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
@@ -38,15 +38,14 @@ import android.service.dreams.DreamService;
import android.service.dreams.IDreamService;
import android.util.Slog;
import android.view.IWindowManager;
-import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
import java.io.PrintWriter;
import java.util.NoSuchElementException;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
-
/**
* Internal controller for starting and stopping the current dream and managing related state.
*
@@ -86,12 +85,9 @@ final class DreamController {
}
};
- private final Runnable mStopStubbornDreamRunnable = new Runnable() {
- @Override
- public void run() {
- Slog.w(TAG, "Stubborn dream did not finish itself in the time allotted");
- stopDream(true /*immediate*/);
- }
+ private final Runnable mStopStubbornDreamRunnable = () -> {
+ Slog.w(TAG, "Stubborn dream did not finish itself in the time allotted");
+ stopDream(true /*immediate*/);
};
public DreamController(Context context, Handler handler, Listener listener) {
@@ -244,12 +240,7 @@ final class DreamController {
Slog.w(TAG, "Error removing window token for dream.", ex);
}
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mListener.onDreamStopped(oldDream.mToken);
- }
- });
+ mHandler.post(() -> mListener.onDreamStopped(oldDream.mToken));
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
@@ -313,13 +304,10 @@ final class DreamController {
// May be called on any thread.
@Override
public void binderDied() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mService = null;
- if (mCurrentDream == DreamRecord.this) {
- stopDream(true /*immediate*/);
- }
+ mHandler.post(() -> {
+ mService = null;
+ if (mCurrentDream == DreamRecord.this) {
+ stopDream(true /*immediate*/);
}
});
}
@@ -327,16 +315,13 @@ final class DreamController {
// May be called on any thread.
@Override
public void onServiceConnected(ComponentName name, final IBinder service) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mConnected = true;
- if (mCurrentDream == DreamRecord.this && mService == null) {
- attach(IDreamService.Stub.asInterface(service));
- // Wake lock will be released once dreaming starts.
- } else {
- releaseWakeLockIfNeeded();
- }
+ mHandler.post(() -> {
+ mConnected = true;
+ if (mCurrentDream == DreamRecord.this && mService == null) {
+ attach(IDreamService.Stub.asInterface(service));
+ // Wake lock will be released once dreaming starts.
+ } else {
+ releaseWakeLockIfNeeded();
}
});
}
@@ -344,13 +329,10 @@ final class DreamController {
// May be called on any thread.
@Override
public void onServiceDisconnected(ComponentName name) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mService = null;
- if (mCurrentDream == DreamRecord.this) {
- stopDream(true /*immediate*/);
- }
+ mHandler.post(() -> {
+ mService = null;
+ if (mCurrentDream == DreamRecord.this) {
+ stopDream(true /*immediate*/);
}
});
}
--
cgit v1.2.3-59-g8ed1b
From 6861e91b84fb444f6a04256bd5d564730660efeb Mon Sep 17 00:00:00 2001
From: Galia Peycheva
Date: Wed, 21 Aug 2019 10:20:23 +0200
Subject: Make DreamService use an Activity
Currently, the DreamService uses a floating Window to display the
content of the dream on the screen. This introduces difficulties in the
interactions with the Assistant application, which is an activity.
By design, if the Assistant is invoked while the device is dreaming, the
Assistant should be shown on top. However, since floating windows are
always drawn on top of all activities, the Assistant can't be shown on
top of the Dream.
Here, we migrate the implementation of the DreamService to use an
Activity (DreamActivity). Since the screensaver application is not part
of the framework, we can't declare the activity in their AndroidManifest.xml.
Therefore, we start the dream activity with a dedicated method in
ActivityTaskManagerService.
Bug: 133216167
Test: 1. m && ./vendor/google/tools/flashall
2. Go to Settings > Device Preferences > Screensaver > Start now
3. Verify dream appears
4. Click any key to wake up the dream
5. Verify that dream disappears
Merged-In: I8dff0a124cd1b41fb925a73528305431b49ee06d
Change-Id: I8dff0a124cd1b41fb925a73528305431b49ee06d
(cherry picked from commit 148478a85e25c86e4b333295dec03aadedc17e1a)
---
core/java/android/app/IActivityTaskManager.aidl | 8 +
.../java/android/service/dreams/DreamActivity.java | 59 +++++
core/java/android/service/dreams/DreamService.java | 245 ++++++++++++---------
core/res/res/values/symbols.xml | 1 +
core/res/res/values/themes.xml | 5 +
.../com/android/server/dreams/DreamController.java | 22 +-
.../com/android/server/wm/ActivityStarter.java | 17 +-
.../server/wm/ActivityTaskManagerService.java | 37 +++-
.../java/com/android/server/wm/AppTaskImpl.java | 2 +-
9 files changed, 264 insertions(+), 132 deletions(-)
create mode 100644 core/java/android/service/dreams/DreamActivity.java
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 5b61402314c4..a55b2c832e41 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -98,6 +98,14 @@ interface IActivityTaskManager {
in ProfilerInfo profilerInfo, in Bundle options, int userId);
boolean startNextMatchingActivity(in IBinder callingActivity,
in Intent intent, in Bundle options);
+
+ /**
+ * The DreamActivity has to be started in a special way that does not involve the PackageParser.
+ * The DreamActivity is a framework component inserted in the dream application process. Hence,
+ * it is not declared in the application's manifest and cannot be parsed. startDreamActivity
+ * creates the activity and starts it without reaching out to the PackageParser.
+ */
+ boolean startDreamActivity(in Intent intent);
int startActivityIntentSender(in IApplicationThread caller,
in IIntentSender target, in IBinder whitelistToken, in Intent fillInIntent,
in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode,
diff --git a/core/java/android/service/dreams/DreamActivity.java b/core/java/android/service/dreams/DreamActivity.java
new file mode 100644
index 000000000000..8cdd24e0884d
--- /dev/null
+++ b/core/java/android/service/dreams/DreamActivity.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 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.annotation.Nullable;
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * The Activity used by the {@link DreamService} to draw screensaver content
+ * on the screen. This activity runs in dream application's process, but is started by a
+ * specialized method: {@link com.android.server.wm.ActivityTaskManagerService#startDreamActivity}.
+ * Hence, it does not have to be declared in the dream application's manifest.
+ *
+ * We use an activity as the dream canvas, because it interacts easier with other activities on
+ * the screen (compared to a hover window). However, the DreamService is in charge of the dream and
+ * it receives all Window.Callbacks from its main window. Since a window can have only one callback
+ * receiver, the activity will not receive any window callbacks.
+ *
+ * Prior to the DreamActivity, the DreamService used to work with a hovering window and give the
+ * screensaver application control over that window. The DreamActivity is a replacement to that
+ * hover window. Using an activity allows for better-defined interactions with the rest of the
+ * activities on screen. The switch to DreamActivity should be transparent to the screensaver
+ * application, i.e. the application will still use DreamService APIs and not notice that the
+ * system is using an activity behind the scenes.
+ *
+ * @hide
+ */
+public class DreamActivity extends Activity {
+ static final String EXTRA_CALLBACK = "binder";
+
+ public DreamActivity() {}
+
+ @Override
+ public void onCreate(@Nullable Bundle bundle) {
+ super.onCreate(bundle);
+
+ DreamService.DreamServiceWrapper callback =
+ (DreamService.DreamServiceWrapper) getIntent().getIBinderExtra(EXTRA_CALLBACK);
+
+ if (callback != null) {
+ callback.onActivityCreated(this);
+ }
+ }
+}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 96a89bcd0120..b31238ca25ca 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -15,25 +15,29 @@
*/
package android.service.dreams;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+
import android.annotation.IdRes;
import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Activity;
+import android.app.ActivityTaskManager;
import android.app.AlarmManager;
import android.app.Service;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.IRemoteCallback;
+import android.os.Looper;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.Log;
import android.util.MathUtils;
import android.util.Slog;
import android.view.ActionMode;
@@ -48,10 +52,8 @@ import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
-import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
-import com.android.internal.policy.PhoneWindow;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.DumpUtils.Dump;
@@ -176,10 +178,11 @@ 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 final IDreamManager mDreamManager;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+ private IBinder mDreamToken;
private Window mWindow;
+ private Activity mActivity;
private boolean mInteractive;
private boolean mLowProfile = true;
private boolean mFullscreen;
@@ -195,8 +198,11 @@ public class DreamService extends Service implements Window.Callback {
private boolean mDebug = false;
+ private DreamServiceWrapper mDreamServiceWrapper;
+ private Runnable mDispatchAfterOnAttachedToWindow;
+
public DreamService() {
- mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
+ mDreamManager = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
}
/**
@@ -670,14 +676,14 @@ public class DreamService extends Service implements Window.Callback {
}
private void updateDoze() {
- if (mWindowToken == null) {
- Slog.w(TAG, "Updating doze without a window token.");
+ if (mDreamToken == null) {
+ Slog.w(TAG, "Updating doze without a dream token.");
return;
}
if (mDozing) {
try {
- mSandman.startDozing(mWindowToken, mDozeScreenState, mDozeScreenBrightness);
+ mDreamManager.startDozing(mDreamToken, mDozeScreenState, mDozeScreenBrightness);
} catch (RemoteException ex) {
// system server died
}
@@ -700,7 +706,7 @@ public class DreamService extends Service implements Window.Callback {
if (mDozing) {
mDozing = false;
try {
- mSandman.stopDozing(mWindowToken);
+ mDreamManager.stopDozing(mDreamToken);
} catch (RemoteException ex) {
// system server died
}
@@ -875,14 +881,15 @@ public class DreamService extends Service implements Window.Callback {
*
*/
public void onWakeUp() {
- finish();
+ mActivity.finishAndRemoveTask();
}
/** {@inheritDoc} */
@Override
public final IBinder onBind(Intent intent) {
if (mDebug) Slog.v(TAG, "onBind() intent = " + intent);
- return new DreamServiceWrapper();
+ mDreamServiceWrapper = new DreamServiceWrapper();
+ return mDreamServiceWrapper;
}
/**
@@ -895,20 +902,29 @@ public class DreamService extends Service implements Window.Callback {
public final void finish() {
if (mDebug) Slog.v(TAG, "finish(): mFinished=" + mFinished);
+ if (mActivity == null) {
+ Slog.w(TAG, "Finish was called before the dream was attached.");
+ return;
+ }
+
+ // In case the activity is not finished yet, do it now. This can happen if someone calls
+ // finish() directly, without going through wakeUp().
+ if (!mActivity.isFinishing()) {
+ mActivity.finishAndRemoveTask();
+ return;
+ }
+
if (!mFinished) {
mFinished = true;
- if (mWindowToken == null) {
- Slog.w(TAG, "Finish was called before the dream was attached.");
- } else {
- try {
- mSandman.finishSelf(mWindowToken, true /*immediate*/);
- } catch (RemoteException ex) {
- // system server died
- }
+ try {
+ // finishSelf will unbind the dream controller from the dream service. This will
+ // trigger DreamService.this.onDestroy and DreamService.this will die.
+ mDreamManager.finishSelf(mDreamToken, true /*immediate*/);
+ } catch (RemoteException ex) {
+ // system server died
}
- stopSelf(); // if launched via any other means
}
}
@@ -938,11 +954,11 @@ public class DreamService extends Service implements Window.Callback {
// Now tell the system we are waking gently, unless we already told
// it we were finishing immediately.
if (!fromSystem && !mFinished) {
- if (mWindowToken == null) {
+ if (mActivity == null) {
Slog.w(TAG, "WakeUp was called before the dream was attached.");
} else {
try {
- mSandman.finishSelf(mWindowToken, false /*immediate*/);
+ mDreamManager.finishSelf(mDreamToken, false /*immediate*/);
} catch (RemoteException ex) {
// system server died
}
@@ -977,20 +993,12 @@ public class DreamService extends Service implements Window.Callback {
onDreamingStopped();
}
- if (mWindow != null) {
- // force our window to be removed synchronously
- if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager");
- mWindow.getWindowManager().removeViewImmediate(mWindow.getDecorView());
- mWindow = null;
+ if (mActivity != null && !mActivity.isFinishing()) {
+ mActivity.finishAndRemoveTask();
}
- if (mWindowToken != null) {
- // the following will print a log message if it finds any other leaked windows
- WindowManagerGlobal.getInstance().closeAll(mWindowToken,
- this.getClass().getName(), "Dream");
- mWindowToken = null;
- mCanDoze = false;
- }
+ mDreamToken = null;
+ mCanDoze = false;
}
/**
@@ -998,95 +1006,107 @@ public class DreamService extends Service implements Window.Callback {
*
* Must run on mHandler.
*
- * @param windowToken A window token that will allow a window to be created in the correct layer.
+ * @param dreamToken Token for this dream service.
* @param started A callback that will be invoked once onDreamingStarted has completed.
*/
- private final void attach(IBinder windowToken, boolean canDoze, IRemoteCallback started) {
- if (mWindowToken != null) {
- Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
+ private void attach(IBinder dreamToken, boolean canDoze, IRemoteCallback started) {
+ if (mActivity != null) {
+ Slog.e(TAG, "attach() called when dream with token=" + mDreamToken
+ + " already attached");
return;
}
if (mFinished || mWaking) {
Slog.w(TAG, "attach() called after dream already finished");
try {
- mSandman.finishSelf(windowToken, true /*immediate*/);
+ mDreamManager.finishSelf(dreamToken, true /*immediate*/);
} catch (RemoteException ex) {
// system server died
}
return;
}
- mWindowToken = windowToken;
+ mDreamToken = dreamToken;
mCanDoze = canDoze;
if (mWindowless && !mCanDoze) {
throw new IllegalStateException("Only doze dreams can be windowless");
}
- if (!mWindowless) {
- mWindow = new PhoneWindow(this);
- mWindow.setCallback(this);
- mWindow.requestFeature(Window.FEATURE_NO_TITLE);
- mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
- mWindow.setFormat(PixelFormat.OPAQUE);
-
- if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
- windowToken, WindowManager.LayoutParams.TYPE_DREAM));
- WindowManager.LayoutParams lp = mWindow.getAttributes();
- lp.type = WindowManager.LayoutParams.TYPE_DREAM;
- lp.token = windowToken;
- lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
- lp.flags |= ( WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
- | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
- | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
- | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
- | (mFullscreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0)
- | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
- );
- mWindow.setAttributes(lp);
- // Workaround: Currently low-profile and in-window system bar backgrounds don't go
- // along well. Dreams usually don't need such bars anyways, so disable them by default.
- mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- mWindow.setWindowManager(null, windowToken, "dream", true);
+ mDispatchAfterOnAttachedToWindow = () -> {
+ if (mWindow != null || mWindowless) {
+ mStarted = true;
+ try {
+ onDreamingStarted();
+ } finally {
+ try {
+ started.sendResult(null);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ };
- applySystemUiVisibilityFlags(
- (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
- View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ // We need to defer calling onDreamingStarted until after the activity is created.
+ // If the dream is windowless, we can call it immediately. Otherwise, we wait
+ // for the DreamActivity to report onActivityCreated via
+ // DreamServiceWrapper.onActivityCreated.
+ if (!mWindowless) {
+ Intent i = new Intent(this, DreamActivity.class);
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ i.putExtra(DreamActivity.EXTRA_CALLBACK, mDreamServiceWrapper);
try {
- getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
- } catch (WindowManager.BadTokenException ex) {
- // This can happen because the dream manager service will remove the token
- // immediately without necessarily waiting for the dream to start.
- // We should receive a finish message soon.
- Slog.i(TAG, "attach() called after window token already removed, dream will "
- + "finish soon");
- mWindow = null;
- return;
+ if (!ActivityTaskManager.getService().startDreamActivity(i)) {
+ detach();
+ return;
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Could not connect to activity task manager to start dream activity");
+ e.rethrowFromSystemServer();
}
+ } else {
+ mDispatchAfterOnAttachedToWindow.run();
}
- // We need to defer calling onDreamingStarted until after onWindowAttached,
- // 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
- // this callback is invoked.
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (mWindow != null || mWindowless) {
- if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
- mStarted = true;
- try {
- onDreamingStarted();
- } finally {
- try {
- started.sendResult(null);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ }
+
+ private void onWindowCreated(Window w) {
+ mWindow = w;
+ mWindow.setCallback(this);
+ mWindow.setType(TYPE_DREAM);
+ mWindow.requestFeature(Window.FEATURE_NO_TITLE);
+
+ WindowManager.LayoutParams lp = mWindow.getAttributes();
+ lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
+ lp.flags |= (WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+ | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+ | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+ | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
+ | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
+ | (mFullscreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0)
+ | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
+ );
+ mWindow.setAttributes(lp);
+ // Workaround: Currently low-profile and in-window system bar backgrounds don't go
+ // along well. Dreams usually don't need such bars anyways, so disable them by default.
+ mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+
+ applySystemUiVisibilityFlags(
+ (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
+ View.SYSTEM_UI_FLAG_LOW_PROFILE);
+
+ mWindow.getDecorView().addOnAttachStateChangeListener(
+ new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ mDispatchAfterOnAttachedToWindow.run();
}
- }
- }
- });
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ finish();
+ }
+ });
}
private boolean getWindowFlagValue(int flag, boolean defaultValue) {
@@ -1131,10 +1151,10 @@ public class DreamService extends Service implements Window.Callback {
/** @hide */
protected void dumpOnHandler(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print(TAG + ": ");
- if (mWindowToken == null) {
+ if (mFinished) {
pw.println("stopped");
} else {
- pw.println("running (token=" + mWindowToken + ")");
+ pw.println("running (dreamToken=" + mDreamToken + ")");
}
pw.println(" window: " + mWindow);
pw.print(" flags:");
@@ -1156,11 +1176,16 @@ public class DreamService extends Service implements Window.Callback {
return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
}
- private final class DreamServiceWrapper extends IDreamService.Stub {
+ /**
+ * The DreamServiceWrapper is used as a gateway to the system_server, where DreamController
+ * uses it to control the DreamService. It is also used to receive callbacks from the
+ * DreamActivity.
+ */
+ final class DreamServiceWrapper extends IDreamService.Stub {
@Override
- public void attach(final IBinder windowToken, final boolean canDoze,
+ public void attach(final IBinder dreamToken, final boolean canDoze,
IRemoteCallback started) {
- mHandler.post(() -> DreamService.this.attach(windowToken, canDoze, started));
+ mHandler.post(() -> DreamService.this.attach(dreamToken, canDoze, started));
}
@Override
@@ -1172,5 +1197,11 @@ public class DreamService extends Service implements Window.Callback {
public void wakeUp() {
mHandler.post(() -> DreamService.this.wakeUp(true /*fromSystem*/));
}
+
+ /** @hide */
+ void onActivityCreated(DreamActivity a) {
+ mActivity = a;
+ onWindowCreated(a.getWindow());
+ }
}
}
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d5954596535d..b2b32418afa0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1612,6 +1612,7 @@
+
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 5d9cb48aa5ed..2ef0c927cc61 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -701,6 +701,11 @@ please see themes_device_defaults.xml.
- true
+
+