Merge "Interact with DreamOverlay through distinct clients." into tm-qpr-dev
This commit is contained in:
@@ -36,39 +36,101 @@ import android.view.WindowManager;
|
|||||||
public abstract class DreamOverlayService extends Service {
|
public abstract class DreamOverlayService extends Service {
|
||||||
private static final String TAG = "DreamOverlayService";
|
private static final String TAG = "DreamOverlayService";
|
||||||
private static final boolean DEBUG = false;
|
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
|
@Override
|
||||||
public void startDream(WindowManager.LayoutParams layoutParams,
|
public void startDream(WindowManager.LayoutParams params, IDreamOverlayCallback callback,
|
||||||
IDreamOverlayCallback callback, String dreamComponent,
|
String dreamComponent, boolean shouldShowComplications) throws RemoteException {
|
||||||
boolean shouldShowComplications) {
|
|
||||||
mDreamOverlayCallback = callback;
|
|
||||||
mDreamComponent = ComponentName.unflattenFromString(dreamComponent);
|
mDreamComponent = ComponentName.unflattenFromString(dreamComponent);
|
||||||
mShowComplications = shouldShowComplications;
|
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
|
@Override
|
||||||
public void endDream() {
|
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
|
@Override
|
||||||
public void wakeUp() {
|
public void getClient(IDreamOverlayClientCallback callback) {
|
||||||
onWakeUp(() -> {
|
try {
|
||||||
try {
|
callback.onDreamOverlayClient(
|
||||||
mDreamOverlayCallback.onWakeUpComplete();
|
new OverlayClient(DreamOverlayService.this));
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Could not notify dream of wakeUp:" + e);
|
Log.e(TAG, "could not send client to callback", e);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
IDreamOverlayCallback mDreamOverlayCallback;
|
|
||||||
|
|
||||||
public DreamOverlayService() {
|
public DreamOverlayService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,18 +172,23 @@ public abstract class DreamOverlayService extends Service {
|
|||||||
* This method is invoked to request the dream exit.
|
* This method is invoked to request the dream exit.
|
||||||
*/
|
*/
|
||||||
public final void requestExit() {
|
public final void requestExit() {
|
||||||
try {
|
if (mCurrentClient == null) {
|
||||||
mDreamOverlayCallback.onExitRequested();
|
throw new IllegalStateException("requested exit with no dream present");
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.e(TAG, "Could not request exit:" + e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCurrentClient.onExitRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether to show complications on the dream overlay.
|
* Returns whether to show complications on the dream overlay.
|
||||||
*/
|
*/
|
||||||
public final boolean shouldShowComplications() {
|
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
|
* @hide
|
||||||
*/
|
*/
|
||||||
public final ComponentName getDreamComponent() {
|
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 OverlayConnection mOverlayConnection;
|
||||||
|
|
||||||
private static class OverlayConnection extends PersistentServiceConnection<IDreamOverlay> {
|
private static class OverlayConnection extends PersistentServiceConnection<IDreamOverlay> {
|
||||||
// Overlay set during onBind.
|
// Retrieved Client
|
||||||
private IDreamOverlay mOverlay;
|
private IDreamOverlayClient mClient;
|
||||||
|
|
||||||
// A list of pending requests to execute on the overlay.
|
// 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>() {
|
private final Callback<IDreamOverlay> mCallback = new Callback<IDreamOverlay>() {
|
||||||
@Override
|
@Override
|
||||||
public void onConnected(ObservableServiceConnection<IDreamOverlay> connection,
|
public void onConnected(ObservableServiceConnection<IDreamOverlay> connection,
|
||||||
IDreamOverlay service) {
|
IDreamOverlay service) {
|
||||||
mOverlay = service;
|
try {
|
||||||
for (Consumer<IDreamOverlay> consumer : mConsumers) {
|
service.getClient(mClientCallback);
|
||||||
consumer.accept(mOverlay);
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "could not get DreamOverlayClient", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisconnected(ObservableServiceConnection<IDreamOverlay> connection,
|
public void onDisconnected(ObservableServiceConnection<IDreamOverlay> connection,
|
||||||
int reason) {
|
int reason) {
|
||||||
mOverlay = null;
|
mClient = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -296,16 +310,16 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
super.unbind();
|
super.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addConsumer(Consumer<IDreamOverlay> consumer) {
|
public void addConsumer(Consumer<IDreamOverlayClient> consumer) {
|
||||||
execute(() -> {
|
execute(() -> {
|
||||||
mConsumers.add(consumer);
|
mConsumers.add(consumer);
|
||||||
if (mOverlay != null) {
|
if (mClient != null) {
|
||||||
consumer.accept(mOverlay);
|
consumer.accept(mClient);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeConsumer(Consumer<IDreamOverlay> consumer) {
|
public void removeConsumer(Consumer<IDreamOverlayClient> consumer) {
|
||||||
execute(() -> mConsumers.remove(consumer));
|
execute(() -> mConsumers.remove(consumer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1365,7 +1379,7 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
|
|
||||||
mWindow.getDecorView().addOnAttachStateChangeListener(
|
mWindow.getDecorView().addOnAttachStateChangeListener(
|
||||||
new View.OnAttachStateChangeListener() {
|
new View.OnAttachStateChangeListener() {
|
||||||
private Consumer<IDreamOverlay> mDreamStartOverlayConsumer;
|
private Consumer<IDreamOverlayClient> mDreamStartOverlayConsumer;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewAttachedToWindow(View v) {
|
public void onViewAttachedToWindow(View v) {
|
||||||
|
|||||||
@@ -16,8 +16,7 @@
|
|||||||
|
|
||||||
package android.service.dreams;
|
package android.service.dreams;
|
||||||
|
|
||||||
import android.service.dreams.IDreamOverlayCallback;
|
import android.service.dreams.IDreamOverlayClientCallback;
|
||||||
import android.view.WindowManager.LayoutParams;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link IDreamOverlay} provides a way for a component to annotate a dream with additional view
|
* {@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 {
|
interface IDreamOverlay {
|
||||||
/**
|
/**
|
||||||
* @param params The {@link LayoutParams} for the associated DreamWindow, including the window
|
* Retrieves a client the caller can use to interact with the dream overlay.
|
||||||
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,
|
void getClient(in IDreamOverlayClientCallback 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();
|
|
||||||
}
|
}
|
||||||
|
|||||||
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.os.RemoteException;
|
||||||
import android.service.dreams.IDreamOverlay;
|
import android.service.dreams.IDreamOverlay;
|
||||||
import android.service.dreams.IDreamOverlayCallback;
|
import android.service.dreams.IDreamOverlayCallback;
|
||||||
|
import android.service.dreams.IDreamOverlayClient;
|
||||||
|
import android.service.dreams.IDreamOverlayClientCallback;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -58,6 +60,7 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Captor;
|
import org.mockito.Captor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@@ -148,13 +151,25 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
mDreamOverlayCallbackController);
|
mDreamOverlayCallbackController);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
public IDreamOverlayClient getClient() throws RemoteException {
|
||||||
public void testOnStartMetricsLogged() throws Exception {
|
|
||||||
final IBinder proxy = mService.onBind(new Intent());
|
final IBinder proxy = mService.onBind(new Intent());
|
||||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
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.
|
// Inform the overlay service of dream starting.
|
||||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||||
false /*shouldShowComplication*/);
|
false /*shouldShowComplication*/);
|
||||||
mMainExecutor.runAllReady();
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
@@ -165,11 +180,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOverlayContainerViewAddedToWindow() throws Exception {
|
public void testOverlayContainerViewAddedToWindow() throws Exception {
|
||||||
final IBinder proxy = mService.onBind(new Intent());
|
final IDreamOverlayClient client = getClient();
|
||||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
|
||||||
|
|
||||||
// Inform the overlay service of dream starting.
|
// Inform the overlay service of dream starting.
|
||||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||||
false /*shouldShowComplication*/);
|
false /*shouldShowComplication*/);
|
||||||
mMainExecutor.runAllReady();
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
@@ -178,11 +192,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDreamOverlayContainerViewControllerInitialized() throws Exception {
|
public void testDreamOverlayContainerViewControllerInitialized() throws Exception {
|
||||||
final IBinder proxy = mService.onBind(new Intent());
|
final IDreamOverlayClient client = getClient();
|
||||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
|
||||||
|
|
||||||
// Inform the overlay service of dream starting.
|
// Inform the overlay service of dream starting.
|
||||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||||
false /*shouldShowComplication*/);
|
false /*shouldShowComplication*/);
|
||||||
mMainExecutor.runAllReady();
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
@@ -196,11 +209,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
.thenReturn(mDreamOverlayContainerViewParent)
|
.thenReturn(mDreamOverlayContainerViewParent)
|
||||||
.thenReturn(null);
|
.thenReturn(null);
|
||||||
|
|
||||||
final IBinder proxy = mService.onBind(new Intent());
|
final IDreamOverlayClient client = getClient();
|
||||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
|
||||||
|
|
||||||
// Inform the overlay service of dream starting.
|
// Inform the overlay service of dream starting.
|
||||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||||
false /*shouldShowComplication*/);
|
false /*shouldShowComplication*/);
|
||||||
mMainExecutor.runAllReady();
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
@@ -209,11 +221,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testShouldShowComplicationsSetByStartDream() throws RemoteException {
|
public void testShouldShowComplicationsSetByStartDream() throws RemoteException {
|
||||||
final IBinder proxy = mService.onBind(new Intent());
|
final IDreamOverlayClient client = getClient();
|
||||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
|
||||||
|
|
||||||
// Inform the overlay service of dream starting.
|
// Inform the overlay service of dream starting.
|
||||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||||
true /*shouldShowComplication*/);
|
true /*shouldShowComplication*/);
|
||||||
|
|
||||||
assertThat(mService.shouldShowComplications()).isTrue();
|
assertThat(mService.shouldShowComplications()).isTrue();
|
||||||
@@ -221,11 +232,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLowLightSetByStartDream() throws RemoteException {
|
public void testLowLightSetByStartDream() throws RemoteException {
|
||||||
final IBinder proxy = mService.onBind(new Intent());
|
final IDreamOverlayClient client = getClient();
|
||||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
|
||||||
|
|
||||||
// Inform the overlay service of dream starting.
|
// Inform the overlay service of dream starting.
|
||||||
overlay.startDream(mWindowParams, mDreamOverlayCallback,
|
client.startDream(mWindowParams, mDreamOverlayCallback,
|
||||||
LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
|
LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
|
||||||
mMainExecutor.runAllReady();
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
@@ -235,11 +245,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOnEndDream() throws RemoteException {
|
public void testOnEndDream() throws RemoteException {
|
||||||
final IBinder proxy = mService.onBind(new Intent());
|
final IDreamOverlayClient client = getClient();
|
||||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
|
||||||
|
|
||||||
// Inform the overlay service of dream starting.
|
// Inform the overlay service of dream starting.
|
||||||
overlay.startDream(mWindowParams, mDreamOverlayCallback,
|
client.startDream(mWindowParams, mDreamOverlayCallback,
|
||||||
LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
|
LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
|
||||||
mMainExecutor.runAllReady();
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
@@ -261,11 +270,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDestroy() throws RemoteException {
|
public void testDestroy() throws RemoteException {
|
||||||
final IBinder proxy = mService.onBind(new Intent());
|
final IDreamOverlayClient client = getClient();
|
||||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
|
||||||
|
|
||||||
// Inform the overlay service of dream starting.
|
// Inform the overlay service of dream starting.
|
||||||
overlay.startDream(mWindowParams, mDreamOverlayCallback,
|
client.startDream(mWindowParams, mDreamOverlayCallback,
|
||||||
LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
|
LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
|
||||||
mMainExecutor.runAllReady();
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
@@ -305,15 +313,14 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDecorViewNotAddedToWindowAfterDestroy() throws Exception {
|
public void testDecorViewNotAddedToWindowAfterDestroy() throws Exception {
|
||||||
final IBinder proxy = mService.onBind(new Intent());
|
final IDreamOverlayClient client = getClient();
|
||||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
|
||||||
|
|
||||||
// Destroy the service.
|
// Destroy the service.
|
||||||
mService.onDestroy();
|
mService.onDestroy();
|
||||||
mMainExecutor.runAllReady();
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
// Inform the overlay service of dream starting.
|
// Inform the overlay service of dream starting.
|
||||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||||
false /*shouldShowComplication*/);
|
false /*shouldShowComplication*/);
|
||||||
mMainExecutor.runAllReady();
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
@@ -331,11 +338,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResetCurrentOverlayWhenConnectedToNewDream() throws RemoteException {
|
public void testResetCurrentOverlayWhenConnectedToNewDream() throws RemoteException {
|
||||||
final IBinder proxy = mService.onBind(new Intent());
|
final IDreamOverlayClient client = getClient();
|
||||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
|
||||||
|
|
||||||
// Inform the overlay service of dream starting. Do not show dream complications.
|
// 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*/);
|
false /*shouldShowComplication*/);
|
||||||
mMainExecutor.runAllReady();
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
@@ -352,7 +358,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
// New dream starting with dream complications showing. Note that when a new dream is
|
// 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
|
// binding to the dream overlay service, it receives the same instance of IBinder as the
|
||||||
// first one.
|
// first one.
|
||||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||||
true /*shouldShowComplication*/);
|
true /*shouldShowComplication*/);
|
||||||
mMainExecutor.runAllReady();
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
@@ -371,11 +377,10 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWakeUp() throws RemoteException {
|
public void testWakeUp() throws RemoteException {
|
||||||
final IBinder proxy = mService.onBind(new Intent());
|
final IDreamOverlayClient client = getClient();
|
||||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
|
||||||
|
|
||||||
// Inform the overlay service of dream starting.
|
// Inform the overlay service of dream starting.
|
||||||
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||||
true /*shouldShowComplication*/);
|
true /*shouldShowComplication*/);
|
||||||
mMainExecutor.runAllReady();
|
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