Merge "IDreamOverlay Introduction."
This commit is contained in:
@@ -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;
|
||||
@@ -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").
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
37
core/java/android/service/dreams/IDreamOverlay.aidl
Normal file
37
core/java/android/service/dreams/IDreamOverlay.aidl
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
31
core/java/android/service/dreams/IDreamOverlayCallback.aidl
Normal file
31
core/java/android/service/dreams/IDreamOverlayCallback.aidl
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
@@ -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");
|
||||
@@ -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,
|
||||
|
||||
@@ -95,6 +95,8 @@ public final class DreamManagerService extends SystemService {
|
||||
private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
|
||||
private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
|
||||
|
||||
private ComponentName mDreamOverlayServiceName;
|
||||
|
||||
private AmbientDisplayConfiguration mDozeConfig;
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -421,7 +423,8 @@ public final class DreamManagerService extends SystemService {
|
||||
if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) {
|
||||
mUiEventLogger.log(DreamManagerEvent.DREAM_START);
|
||||
}
|
||||
mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock);
|
||||
mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock,
|
||||
mDreamOverlayServiceName);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -591,6 +594,15 @@ public final class DreamManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void registerDreamOverlayService(ComponentName overlayComponent) {
|
||||
checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
|
||||
|
||||
// Store the overlay service component so that it can be passed to the dream when it is
|
||||
// invoked.
|
||||
mDreamOverlayServiceName = overlayComponent;
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public ComponentName getDefaultDreamComponentForUser(int userId) {
|
||||
checkPermission(android.Manifest.permission.READ_DREAM_STATE);
|
||||
|
||||
Reference in New Issue
Block a user