Loading core/java/android/service/dreams/DreamService.java +94 −0 Original line number Diff line number Diff line Loading @@ -26,7 +26,10 @@ import android.app.ActivityTaskManager; import android.app.AlarmManager; import android.app.Service; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Build; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -58,6 +61,8 @@ import com.android.internal.util.DumpUtils.Dump; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.function.Consumer; /** * Extend this class to implement a custom dream (available to the user as a "Daydream"). Loading Loading @@ -169,6 +174,13 @@ public class DreamService extends Service implements Window.Callback { public static final String SERVICE_INTERFACE = "android.service.dreams.DreamService"; /** * The name of the extra where the dream overlay component is stored. * @hide */ public static final String EXTRA_DREAM_OVERLAY_COMPONENT = "android.service.dream.DreamService.dream_overlay_component"; /** * Name under which a Dream publishes information about itself. * This meta-data must reference an XML resource containing Loading @@ -191,6 +203,7 @@ public class DreamService extends Service implements Window.Callback { private boolean mCanDoze; private boolean mDozing; private boolean mWindowless; private boolean mOverlayServiceBound; private int mDozeScreenState = Display.STATE_UNKNOWN; private int mDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; Loading @@ -199,8 +212,62 @@ public class DreamService extends Service implements Window.Callback { private DreamServiceWrapper mDreamServiceWrapper; private Runnable mDispatchAfterOnAttachedToWindow; private OverlayConnection mOverlayConnection; private static class OverlayConnection implements ServiceConnection { // Overlay set during onBind. private IDreamOverlay mOverlay; // A Queue of pending requests to execute on the overlay. private ArrayDeque<Consumer<IDreamOverlay>> mRequests; OverlayConnection() { mRequests = new ArrayDeque<>(); } public void request(Consumer<IDreamOverlay> request) { mRequests.push(request); evaluate(); } private void evaluate() { if (mOverlay == null) { return; } // Any new requests that arrive during this loop will be processed synchronously after // the loop exits. while (!mRequests.isEmpty()) { final Consumer<IDreamOverlay> request = mRequests.pop(); request.accept(mOverlay); } } @Override public void onServiceConnected(ComponentName name, IBinder service) { // Store Overlay and execute pending requests. mOverlay = IDreamOverlay.Stub.asInterface(service); evaluate(); } @Override public void onServiceDisconnected(ComponentName name) { // Clear Overlay binder to prevent further request processing. mOverlay = null; } } private IDreamOverlayCallback mOverlayCallback = new IDreamOverlayCallback.Stub() { @Override public void onExitRequested() { // Simply finish dream when exit is requested. finish(); } }; public DreamService() { mDreamManager = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE)); mOverlayConnection = new OverlayConnection(); } /** Loading Loading @@ -861,6 +928,18 @@ public class DreamService extends Service implements Window.Callback { public final IBinder onBind(Intent intent) { if (mDebug) Slog.v(TAG, "onBind() intent = " + intent); mDreamServiceWrapper = new DreamServiceWrapper(); // Connect to the overlay service if present. final ComponentName overlayComponent = intent.getParcelableExtra(EXTRA_DREAM_OVERLAY_COMPONENT); if (overlayComponent != null && !mWindowless) { final Intent overlayIntent = new Intent(); overlayIntent.setComponent(overlayComponent); mOverlayServiceBound = getApplicationContext().bindService(overlayIntent, mOverlayConnection, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE); } return mDreamServiceWrapper; } Loading Loading @@ -894,6 +973,11 @@ public class DreamService extends Service implements Window.Callback { return; } if (!mWindowless && mOverlayServiceBound) { unbindService(mOverlayConnection); mOverlayServiceBound = false; } try { // finishSelf will unbind the dream controller from the dream service. This will // trigger DreamService.this.onDestroy and DreamService.this will die. Loading Loading @@ -1101,6 +1185,16 @@ public class DreamService extends Service implements Window.Callback { } } }); // Request the DreamOverlay be told to dream with dream's window parameters once the service // has connected. mOverlayConnection.request(overlay -> { try { overlay.startDream(mWindow.getAttributes(), mOverlayCallback); } catch (RemoteException e) { Log.e(TAG, "could not send window attributes:" + e); } }); } private boolean getWindowFlagValue(int flag, boolean defaultValue) { Loading core/java/android/service/dreams/IDreamManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -41,4 +41,5 @@ interface IDreamManager { void forceAmbientDisplayEnabled(boolean enabled); ComponentName[] getDreamComponentsForUser(int userId); void setDreamComponentsForUser(int userId, in ComponentName[] componentNames); void registerDreamOverlayService(in ComponentName componentName); } core/java/android/service/dreams/IDreamOverlay.aidl 0 → 100644 +37 −0 Original line number Diff line number Diff line /** * Copyright (c) 2021, 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.service.dreams.IDreamOverlayCallback; import android.view.WindowManager.LayoutParams; /** * {@link IDreamOverlay} provides a way for a component to annotate a dream with additional view * elements. Registered through the DreamManager, a IDreamOverlay is bound to by the dream and * passed the necessary window details to participate in the user interface. * @hide */ interface IDreamOverlay { /** * @param params The {@link LayoutParams} for the associated DreamWindow, including the window token of the Dream Activity. * @param callback The {@link IDreamOverlayCallback} for requesting actions such as exiting the * dream. */ void startDream(in LayoutParams params, in IDreamOverlayCallback callback); } core/java/android/service/dreams/IDreamOverlayCallback.aidl 0 → 100644 +31 −0 Original line number Diff line number Diff line /** * Copyright (c) 2021, 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; /** * {@link IDreamOverlayCallback} defines the interactions a dream overlay can have with its * associated dream. It is the discretion of the {@link DreamService}) to honor any inbound requests * from this callback. * * @hide */ interface IDreamOverlayCallback { /** * Invoked to request the dream exit. */ void onExitRequested(); } No newline at end of file services/core/java/com/android/server/dreams/DreamController.java +3 −1 Original line number Diff line number Diff line Loading @@ -117,7 +117,8 @@ final class DreamController { } public void startDream(Binder token, ComponentName name, boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock) { boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock, ComponentName overlayComponentName) { stopDream(true /*immediate*/, "starting new dream"); Trace.traceBegin(Trace.TRACE_TAG_POWER, "startDream"); Loading @@ -138,6 +139,7 @@ final class DreamController { Intent intent = new Intent(DreamService.SERVICE_INTERFACE); intent.setComponent(name); intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(DreamService.EXTRA_DREAM_OVERLAY_COMPONENT, overlayComponentName); try { if (!mContext.bindServiceAsUser(intent, mCurrentDream, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, Loading Loading
core/java/android/service/dreams/DreamService.java +94 −0 Original line number Diff line number Diff line Loading @@ -26,7 +26,10 @@ import android.app.ActivityTaskManager; import android.app.AlarmManager; import android.app.Service; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Build; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -58,6 +61,8 @@ import com.android.internal.util.DumpUtils.Dump; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.function.Consumer; /** * Extend this class to implement a custom dream (available to the user as a "Daydream"). Loading Loading @@ -169,6 +174,13 @@ public class DreamService extends Service implements Window.Callback { public static final String SERVICE_INTERFACE = "android.service.dreams.DreamService"; /** * The name of the extra where the dream overlay component is stored. * @hide */ public static final String EXTRA_DREAM_OVERLAY_COMPONENT = "android.service.dream.DreamService.dream_overlay_component"; /** * Name under which a Dream publishes information about itself. * This meta-data must reference an XML resource containing Loading @@ -191,6 +203,7 @@ public class DreamService extends Service implements Window.Callback { private boolean mCanDoze; private boolean mDozing; private boolean mWindowless; private boolean mOverlayServiceBound; private int mDozeScreenState = Display.STATE_UNKNOWN; private int mDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; Loading @@ -199,8 +212,62 @@ public class DreamService extends Service implements Window.Callback { private DreamServiceWrapper mDreamServiceWrapper; private Runnable mDispatchAfterOnAttachedToWindow; private OverlayConnection mOverlayConnection; private static class OverlayConnection implements ServiceConnection { // Overlay set during onBind. private IDreamOverlay mOverlay; // A Queue of pending requests to execute on the overlay. private ArrayDeque<Consumer<IDreamOverlay>> mRequests; OverlayConnection() { mRequests = new ArrayDeque<>(); } public void request(Consumer<IDreamOverlay> request) { mRequests.push(request); evaluate(); } private void evaluate() { if (mOverlay == null) { return; } // Any new requests that arrive during this loop will be processed synchronously after // the loop exits. while (!mRequests.isEmpty()) { final Consumer<IDreamOverlay> request = mRequests.pop(); request.accept(mOverlay); } } @Override public void onServiceConnected(ComponentName name, IBinder service) { // Store Overlay and execute pending requests. mOverlay = IDreamOverlay.Stub.asInterface(service); evaluate(); } @Override public void onServiceDisconnected(ComponentName name) { // Clear Overlay binder to prevent further request processing. mOverlay = null; } } private IDreamOverlayCallback mOverlayCallback = new IDreamOverlayCallback.Stub() { @Override public void onExitRequested() { // Simply finish dream when exit is requested. finish(); } }; public DreamService() { mDreamManager = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE)); mOverlayConnection = new OverlayConnection(); } /** Loading Loading @@ -861,6 +928,18 @@ public class DreamService extends Service implements Window.Callback { public final IBinder onBind(Intent intent) { if (mDebug) Slog.v(TAG, "onBind() intent = " + intent); mDreamServiceWrapper = new DreamServiceWrapper(); // Connect to the overlay service if present. final ComponentName overlayComponent = intent.getParcelableExtra(EXTRA_DREAM_OVERLAY_COMPONENT); if (overlayComponent != null && !mWindowless) { final Intent overlayIntent = new Intent(); overlayIntent.setComponent(overlayComponent); mOverlayServiceBound = getApplicationContext().bindService(overlayIntent, mOverlayConnection, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE); } return mDreamServiceWrapper; } Loading Loading @@ -894,6 +973,11 @@ public class DreamService extends Service implements Window.Callback { return; } if (!mWindowless && mOverlayServiceBound) { unbindService(mOverlayConnection); mOverlayServiceBound = false; } try { // finishSelf will unbind the dream controller from the dream service. This will // trigger DreamService.this.onDestroy and DreamService.this will die. Loading Loading @@ -1101,6 +1185,16 @@ public class DreamService extends Service implements Window.Callback { } } }); // Request the DreamOverlay be told to dream with dream's window parameters once the service // has connected. mOverlayConnection.request(overlay -> { try { overlay.startDream(mWindow.getAttributes(), mOverlayCallback); } catch (RemoteException e) { Log.e(TAG, "could not send window attributes:" + e); } }); } private boolean getWindowFlagValue(int flag, boolean defaultValue) { Loading
core/java/android/service/dreams/IDreamManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -41,4 +41,5 @@ interface IDreamManager { void forceAmbientDisplayEnabled(boolean enabled); ComponentName[] getDreamComponentsForUser(int userId); void setDreamComponentsForUser(int userId, in ComponentName[] componentNames); void registerDreamOverlayService(in ComponentName componentName); }
core/java/android/service/dreams/IDreamOverlay.aidl 0 → 100644 +37 −0 Original line number Diff line number Diff line /** * Copyright (c) 2021, 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.service.dreams.IDreamOverlayCallback; import android.view.WindowManager.LayoutParams; /** * {@link IDreamOverlay} provides a way for a component to annotate a dream with additional view * elements. Registered through the DreamManager, a IDreamOverlay is bound to by the dream and * passed the necessary window details to participate in the user interface. * @hide */ interface IDreamOverlay { /** * @param params The {@link LayoutParams} for the associated DreamWindow, including the window token of the Dream Activity. * @param callback The {@link IDreamOverlayCallback} for requesting actions such as exiting the * dream. */ void startDream(in LayoutParams params, in IDreamOverlayCallback callback); }
core/java/android/service/dreams/IDreamOverlayCallback.aidl 0 → 100644 +31 −0 Original line number Diff line number Diff line /** * Copyright (c) 2021, 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; /** * {@link IDreamOverlayCallback} defines the interactions a dream overlay can have with its * associated dream. It is the discretion of the {@link DreamService}) to honor any inbound requests * from this callback. * * @hide */ interface IDreamOverlayCallback { /** * Invoked to request the dream exit. */ void onExitRequested(); } No newline at end of file
services/core/java/com/android/server/dreams/DreamController.java +3 −1 Original line number Diff line number Diff line Loading @@ -117,7 +117,8 @@ final class DreamController { } public void startDream(Binder token, ComponentName name, boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock) { boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock, ComponentName overlayComponentName) { stopDream(true /*immediate*/, "starting new dream"); Trace.traceBegin(Trace.TRACE_TAG_POWER, "startDream"); Loading @@ -138,6 +139,7 @@ final class DreamController { Intent intent = new Intent(DreamService.SERVICE_INTERFACE); intent.setComponent(name); intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(DreamService.EXTRA_DREAM_OVERLAY_COMPONENT, overlayComponentName); try { if (!mContext.bindServiceAsUser(intent, mCurrentDream, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, Loading