Merge "Interact with DreamOverlay through distinct clients." into tm-qpr-dev am: b928049681 am: cf8cfa3c23
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21109634 Change-Id: I1551c3a299b0dacb01787b57b5ed1c2a06c9c5c7 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -36,39 +36,101 @@ import android.view.WindowManager;
|
||||
public abstract class DreamOverlayService extends Service {
|
||||
private static final String TAG = "DreamOverlayService";
|
||||
private static final boolean DEBUG = false;
|
||||
private boolean mShowComplications;
|
||||
private ComponentName mDreamComponent;
|
||||
|
||||
private IDreamOverlay mDreamOverlay = new IDreamOverlay.Stub() {
|
||||
// The last client that started dreaming and hasn't ended
|
||||
private OverlayClient mCurrentClient;
|
||||
|
||||
// An {@link IDreamOverlayClient} implementation that identifies itself when forwarding
|
||||
// requests to the {@link DreamOverlayService}
|
||||
private static class OverlayClient extends IDreamOverlayClient.Stub {
|
||||
private final DreamOverlayService mService;
|
||||
private boolean mShowComplications;
|
||||
private ComponentName mDreamComponent;
|
||||
IDreamOverlayCallback mDreamOverlayCallback;
|
||||
|
||||
OverlayClient(DreamOverlayService service) {
|
||||
mService = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDream(WindowManager.LayoutParams layoutParams,
|
||||
IDreamOverlayCallback callback, String dreamComponent,
|
||||
boolean shouldShowComplications) {
|
||||
mDreamOverlayCallback = callback;
|
||||
public void startDream(WindowManager.LayoutParams params, IDreamOverlayCallback callback,
|
||||
String dreamComponent, boolean shouldShowComplications) throws RemoteException {
|
||||
mDreamComponent = ComponentName.unflattenFromString(dreamComponent);
|
||||
mShowComplications = shouldShowComplications;
|
||||
onStartDream(layoutParams);
|
||||
mDreamOverlayCallback = callback;
|
||||
mService.startDream(this, params);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void wakeUp() {
|
||||
mService.wakeUp(this, () -> {
|
||||
try {
|
||||
mDreamOverlayCallback.onWakeUpComplete();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not notify dream of wakeUp", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDream() {
|
||||
onEndDream();
|
||||
mService.endDream(this);
|
||||
}
|
||||
|
||||
private void onExitRequested() {
|
||||
try {
|
||||
mDreamOverlayCallback.onExitRequested();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not request exit:" + e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldShowComplications() {
|
||||
return mShowComplications;
|
||||
}
|
||||
|
||||
private ComponentName getComponent() {
|
||||
return mDreamComponent;
|
||||
}
|
||||
}
|
||||
|
||||
private void startDream(OverlayClient client, WindowManager.LayoutParams params) {
|
||||
endDream(mCurrentClient);
|
||||
mCurrentClient = client;
|
||||
onStartDream(params);
|
||||
}
|
||||
|
||||
private void endDream(OverlayClient client) {
|
||||
if (client == null || client != mCurrentClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
onEndDream();
|
||||
mCurrentClient = null;
|
||||
}
|
||||
|
||||
private void wakeUp(OverlayClient client, Runnable callback) {
|
||||
if (mCurrentClient != client) {
|
||||
return;
|
||||
}
|
||||
|
||||
onWakeUp(callback);
|
||||
}
|
||||
|
||||
private IDreamOverlay mDreamOverlay = new IDreamOverlay.Stub() {
|
||||
@Override
|
||||
public void wakeUp() {
|
||||
onWakeUp(() -> {
|
||||
try {
|
||||
mDreamOverlayCallback.onWakeUpComplete();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not notify dream of wakeUp:" + e);
|
||||
}
|
||||
});
|
||||
public void getClient(IDreamOverlayClientCallback callback) {
|
||||
try {
|
||||
callback.onDreamOverlayClient(
|
||||
new OverlayClient(DreamOverlayService.this));
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "could not send client to callback", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IDreamOverlayCallback mDreamOverlayCallback;
|
||||
|
||||
public DreamOverlayService() {
|
||||
}
|
||||
|
||||
@@ -110,18 +172,23 @@ public abstract class DreamOverlayService extends Service {
|
||||
* This method is invoked to request the dream exit.
|
||||
*/
|
||||
public final void requestExit() {
|
||||
try {
|
||||
mDreamOverlayCallback.onExitRequested();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not request exit:" + e);
|
||||
if (mCurrentClient == null) {
|
||||
throw new IllegalStateException("requested exit with no dream present");
|
||||
}
|
||||
|
||||
mCurrentClient.onExitRequested();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to show complications on the dream overlay.
|
||||
*/
|
||||
public final boolean shouldShowComplications() {
|
||||
return mShowComplications;
|
||||
if (mCurrentClient == null) {
|
||||
throw new IllegalStateException(
|
||||
"requested if should show complication when no dream active");
|
||||
}
|
||||
|
||||
return mCurrentClient.shouldShowComplications();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,6 +196,10 @@ public abstract class DreamOverlayService extends Service {
|
||||
* @hide
|
||||
*/
|
||||
public final ComponentName getDreamComponent() {
|
||||
return mDreamComponent;
|
||||
if (mCurrentClient == null) {
|
||||
throw new IllegalStateException("requested dream component when no dream active");
|
||||
}
|
||||
|
||||
return mCurrentClient.getComponent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,25 +248,39 @@ public class DreamService extends Service implements Window.Callback {
|
||||
private OverlayConnection mOverlayConnection;
|
||||
|
||||
private static class OverlayConnection extends PersistentServiceConnection<IDreamOverlay> {
|
||||
// Overlay set during onBind.
|
||||
private IDreamOverlay mOverlay;
|
||||
// Retrieved Client
|
||||
private IDreamOverlayClient mClient;
|
||||
|
||||
// A list of pending requests to execute on the overlay.
|
||||
private final ArrayList<Consumer<IDreamOverlay>> mConsumers = new ArrayList<>();
|
||||
private final ArrayList<Consumer<IDreamOverlayClient>> mConsumers = new ArrayList<>();
|
||||
|
||||
private final IDreamOverlayClientCallback mClientCallback =
|
||||
new IDreamOverlayClientCallback.Stub() {
|
||||
@Override
|
||||
public void onDreamOverlayClient(IDreamOverlayClient client) {
|
||||
mClient = client;
|
||||
|
||||
for (Consumer<IDreamOverlayClient> consumer : mConsumers) {
|
||||
consumer.accept(mClient);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Callback<IDreamOverlay> mCallback = new Callback<IDreamOverlay>() {
|
||||
@Override
|
||||
public void onConnected(ObservableServiceConnection<IDreamOverlay> connection,
|
||||
IDreamOverlay service) {
|
||||
mOverlay = service;
|
||||
for (Consumer<IDreamOverlay> consumer : mConsumers) {
|
||||
consumer.accept(mOverlay);
|
||||
try {
|
||||
service.getClient(mClientCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "could not get DreamOverlayClient", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(ObservableServiceConnection<IDreamOverlay> connection,
|
||||
int reason) {
|
||||
mOverlay = null;
|
||||
mClient = null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -296,16 +310,16 @@ public class DreamService extends Service implements Window.Callback {
|
||||
super.unbind();
|
||||
}
|
||||
|
||||
public void addConsumer(Consumer<IDreamOverlay> consumer) {
|
||||
public void addConsumer(Consumer<IDreamOverlayClient> consumer) {
|
||||
execute(() -> {
|
||||
mConsumers.add(consumer);
|
||||
if (mOverlay != null) {
|
||||
consumer.accept(mOverlay);
|
||||
if (mClient != null) {
|
||||
consumer.accept(mClient);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void removeConsumer(Consumer<IDreamOverlay> consumer) {
|
||||
public void removeConsumer(Consumer<IDreamOverlayClient> consumer) {
|
||||
execute(() -> mConsumers.remove(consumer));
|
||||
}
|
||||
|
||||
@@ -1379,7 +1393,7 @@ public class DreamService extends Service implements Window.Callback {
|
||||
|
||||
mWindow.getDecorView().addOnAttachStateChangeListener(
|
||||
new View.OnAttachStateChangeListener() {
|
||||
private Consumer<IDreamOverlay> mDreamStartOverlayConsumer;
|
||||
private Consumer<IDreamOverlayClient> mDreamStartOverlayConsumer;
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View v) {
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
|
||||
package android.service.dreams;
|
||||
|
||||
import android.service.dreams.IDreamOverlayCallback;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.service.dreams.IDreamOverlayClientCallback;
|
||||
|
||||
/**
|
||||
* {@link IDreamOverlay} provides a way for a component to annotate a dream with additional view
|
||||
@@ -28,20 +27,7 @@ import android.view.WindowManager.LayoutParams;
|
||||
*/
|
||||
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.
|
||||
* @param dreamComponent The component name of the dream service requesting overlay.
|
||||
* @param shouldShowComplications Whether the dream overlay should show complications, e.g. clock
|
||||
* and weather.
|
||||
* Retrieves a client the caller can use to interact with the dream overlay.
|
||||
*/
|
||||
void startDream(in LayoutParams params, in IDreamOverlayCallback callback,
|
||||
in String dreamComponent, in boolean shouldShowComplications);
|
||||
|
||||
/** Called when the dream is waking, to do any exit animations */
|
||||
void wakeUp();
|
||||
|
||||
/** Called when the dream has ended. */
|
||||
void endDream();
|
||||
void getClient(in IDreamOverlayClientCallback callback);
|
||||
}
|
||||
|
||||
45
core/java/android/service/dreams/IDreamOverlayClient.aidl
Normal file
45
core/java/android/service/dreams/IDreamOverlayClient.aidl
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2023, 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 IDreamOverlayClient} allows {@link DreamService} instances to act upon the dream overlay.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
interface IDreamOverlayClient {
|
||||
/**
|
||||
* @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.
|
||||
* @param dreamComponent The component name of the dream service requesting overlay.
|
||||
* @param shouldShowComplications Whether the dream overlay should show complications, e.g. clock
|
||||
* and weather.
|
||||
*/
|
||||
void startDream(in LayoutParams params, in IDreamOverlayCallback callback,
|
||||
in String dreamComponent, in boolean shouldShowComplications);
|
||||
|
||||
/** Called when the dream is waking, to do any exit animations */
|
||||
void wakeUp();
|
||||
|
||||
/** Called when the dream has ended. */
|
||||
void endDream();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2023, 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.IDreamOverlayClient;
|
||||
|
||||
/**
|
||||
* {@link IDreamOverlayClientCallback} allows receiving a requested {@link IDreamOverlayClient}.
|
||||
* @hide
|
||||
*/
|
||||
interface IDreamOverlayClientCallback {
|
||||
/**
|
||||
* Called with a unique {@link IDreamOverlayClient}.
|
||||
*/
|
||||
void onDreamOverlayClient(in IDreamOverlayClient client);
|
||||
}
|
||||
@@ -31,6 +31,8 @@ import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.service.dreams.IDreamOverlay;
|
||||
import android.service.dreams.IDreamOverlayCallback;
|
||||
import android.service.dreams.IDreamOverlayClient;
|
||||
import android.service.dreams.IDreamOverlayClientCallback;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -61,6 +63,7 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@@ -189,13 +192,25 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
mDreamOverlayCallbackController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnStartMetricsLogged() throws Exception {
|
||||
public IDreamOverlayClient getClient() throws RemoteException {
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
final IDreamOverlayClientCallback callback =
|
||||
Mockito.mock(IDreamOverlayClientCallback.class);
|
||||
overlay.getClient(callback);
|
||||
final ArgumentCaptor<IDreamOverlayClient> clientCaptor =
|
||||
ArgumentCaptor.forClass(IDreamOverlayClient.class);
|
||||
verify(callback).onDreamOverlayClient(clientCaptor.capture());
|
||||
|
||||
return clientCaptor.getValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnStartMetricsLogged() throws Exception {
|
||||
final IDreamOverlayClient client = getClient();
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
false /*shouldShowComplication*/);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
@@ -206,11 +221,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testOverlayContainerViewAddedToWindow() throws Exception {
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
final IDreamOverlayClient client = getClient();
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
false /*shouldShowComplication*/);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
@@ -219,11 +233,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testDreamOverlayContainerViewControllerInitialized() throws Exception {
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
final IDreamOverlayClient client = getClient();
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
false /*shouldShowComplication*/);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
@@ -237,11 +250,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
.thenReturn(mDreamOverlayContainerViewParent)
|
||||
.thenReturn(null);
|
||||
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
final IDreamOverlayClient client = getClient();
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
false /*shouldShowComplication*/);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
@@ -250,11 +262,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testShouldShowComplicationsSetByStartDream() throws RemoteException {
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
final IDreamOverlayClient client = getClient();
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
true /*shouldShowComplication*/);
|
||||
|
||||
assertThat(mService.shouldShowComplications()).isTrue();
|
||||
@@ -262,11 +273,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testLowLightSetByStartDream() throws RemoteException {
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
final IDreamOverlayClient client = getClient();
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback,
|
||||
LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
@@ -276,11 +286,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testOnEndDream() throws RemoteException {
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
final IDreamOverlayClient client = getClient();
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback,
|
||||
LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
@@ -302,11 +311,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testDestroy() throws RemoteException {
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
final IDreamOverlayClient client = getClient();
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback,
|
||||
LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
@@ -346,15 +354,14 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testDecorViewNotAddedToWindowAfterDestroy() throws Exception {
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
final IDreamOverlayClient client = getClient();
|
||||
|
||||
// Destroy the service.
|
||||
mService.onDestroy();
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
false /*shouldShowComplication*/);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
@@ -372,11 +379,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testResetCurrentOverlayWhenConnectedToNewDream() throws RemoteException {
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
final IDreamOverlayClient client = getClient();
|
||||
|
||||
// Inform the overlay service of dream starting. Do not show dream complications.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
false /*shouldShowComplication*/);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
@@ -393,7 +399,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
// New dream starting with dream complications showing. Note that when a new dream is
|
||||
// binding to the dream overlay service, it receives the same instance of IBinder as the
|
||||
// first one.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
true /*shouldShowComplication*/);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
@@ -412,11 +418,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testWakeUp() throws RemoteException {
|
||||
final IBinder proxy = mService.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
final IDreamOverlayClient client = getClient();
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||
true /*shouldShowComplication*/);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.service.dreams.DreamOverlayService;
|
||||
import android.service.dreams.IDreamOverlay;
|
||||
import android.service.dreams.IDreamOverlayCallback;
|
||||
import android.service.dreams.IDreamOverlayClient;
|
||||
import android.service.dreams.IDreamOverlayClientCallback;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/**
|
||||
* A collection of tests to exercise {@link DreamOverlayService}.
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DreamOverlayServiceTest {
|
||||
private static final ComponentName FIRST_DREAM_COMPONENT =
|
||||
ComponentName.unflattenFromString("com.foo.bar/.DreamService");
|
||||
private static final ComponentName SECOND_DREAM_COMPONENT =
|
||||
ComponentName.unflattenFromString("com.foo.baz/.DreamService");
|
||||
|
||||
@Mock
|
||||
WindowManager.LayoutParams mLayoutParams;
|
||||
|
||||
@Mock
|
||||
IDreamOverlayCallback mOverlayCallback;
|
||||
|
||||
/**
|
||||
* {@link TestDreamOverlayService} is a simple {@link DreamOverlayService} implementation for
|
||||
* tracking interactions across {@link IDreamOverlay} binder interface. The service reports
|
||||
* interactions to a {@link Monitor} instance provided at construction.
|
||||
*/
|
||||
private static class TestDreamOverlayService extends DreamOverlayService {
|
||||
/**
|
||||
* An interface implemented to be informed when the corresponding methods in
|
||||
* {@link TestDreamOverlayService} are invoked.
|
||||
*/
|
||||
interface Monitor {
|
||||
void onStartDream();
|
||||
void onEndDream();
|
||||
void onWakeUp();
|
||||
}
|
||||
|
||||
private final Monitor mMonitor;
|
||||
|
||||
TestDreamOverlayService(Monitor monitor) {
|
||||
super();
|
||||
mMonitor = monitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartDream(@NonNull WindowManager.LayoutParams layoutParams) {
|
||||
mMonitor.onStartDream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEndDream() {
|
||||
mMonitor.onEndDream();
|
||||
super.onEndDream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWakeUp(@NonNull Runnable onCompleteCallback) {
|
||||
mMonitor.onWakeUp();
|
||||
super.onWakeUp(onCompleteCallback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link IDreamOverlayClientCallback} implementation that captures the requested client.
|
||||
*/
|
||||
private static class OverlayClientCallback extends IDreamOverlayClientCallback.Stub {
|
||||
public IDreamOverlayClient retrievedClient;
|
||||
@Override
|
||||
public void onDreamOverlayClient(IDreamOverlayClient client) throws RemoteException {
|
||||
retrievedClient = client;
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that only the currently started dream is able to affect the overlay.
|
||||
*/
|
||||
@Test
|
||||
public void testOverlayClientInteraction() throws RemoteException {
|
||||
final TestDreamOverlayService.Monitor monitor = Mockito.mock(
|
||||
TestDreamOverlayService.Monitor.class);
|
||||
final TestDreamOverlayService service = new TestDreamOverlayService(monitor);
|
||||
final IBinder binder = service.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(binder);
|
||||
|
||||
// Create two overlay clients and ensure they are unique.
|
||||
final IDreamOverlayClient firstClient = getClient(overlay);
|
||||
assertThat(firstClient).isNotNull();
|
||||
|
||||
final IDreamOverlayClient secondClient = getClient(overlay);
|
||||
assertThat(secondClient).isNotNull();
|
||||
|
||||
assertThat(firstClient).isNotEqualTo(secondClient);
|
||||
|
||||
// Start a dream with the first client and ensure the dream is now active from the
|
||||
// overlay's perspective.
|
||||
firstClient.startDream(mLayoutParams, mOverlayCallback,
|
||||
FIRST_DREAM_COMPONENT.flattenToString(), false);
|
||||
|
||||
|
||||
verify(monitor).onStartDream();
|
||||
assertThat(service.getDreamComponent()).isEqualTo(FIRST_DREAM_COMPONENT);
|
||||
|
||||
Mockito.clearInvocations(monitor);
|
||||
|
||||
// Start a dream from the second client and verify that the overlay has both cycled to
|
||||
// the new dream (ended/started).
|
||||
secondClient.startDream(mLayoutParams, mOverlayCallback,
|
||||
SECOND_DREAM_COMPONENT.flattenToString(), false);
|
||||
|
||||
verify(monitor).onEndDream();
|
||||
verify(monitor).onStartDream();
|
||||
assertThat(service.getDreamComponent()).isEqualTo(SECOND_DREAM_COMPONENT);
|
||||
|
||||
Mockito.clearInvocations(monitor);
|
||||
|
||||
// Verify that interactions with the first, now inactive client don't affect the overlay.
|
||||
firstClient.endDream();
|
||||
verify(monitor, never()).onEndDream();
|
||||
|
||||
firstClient.wakeUp();
|
||||
verify(monitor, never()).onWakeUp();
|
||||
}
|
||||
|
||||
private static IDreamOverlayClient getClient(IDreamOverlay overlay) throws RemoteException {
|
||||
final OverlayClientCallback callback = new OverlayClientCallback();
|
||||
overlay.getClient(callback);
|
||||
return callback.retrievedClient;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user