diff options
| author | 2023-04-05 22:06:13 +0000 | |
|---|---|---|
| committer | 2023-04-20 02:24:18 +0000 | |
| commit | c45e60c5ad7206585eef3fcbe0f60e481d5f8747 (patch) | |
| tree | 71e4d652b38a5076388b3e37d9a07e42cc02449f | |
| parent | 4a88a91a1f9ac03eeac5b96677b9bac88bb8055b (diff) | |
Send dream state updates through DreamManagerStateListener.
This changelist extends DreamManagerStateListener to also send updates
about the dream state, including when the dream started and stopped.
This allows system server components to receive state updates without
needed to listen to the dream state broadcasts.
Test: atest DreamControllerTest#startDream_dreamListenerNotified
Test: atest DreamControllerTest#stopDream_dreamListenerNotified
Bug: 275108597
Change-Id: Ifb1e1266b938d50e0744aa106557c8c7db52f442
6 files changed, 103 insertions, 23 deletions
diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java index 82571db469be..e9bb28c252e0 100644 --- a/core/java/android/service/dreams/DreamManagerInternal.java +++ b/core/java/android/service/dreams/DreamManagerInternal.java @@ -84,6 +84,19 @@ public abstract class DreamManagerInternal { * * @param keepDreaming True if the current dream should continue when undocking. */ - void onKeepDreamingWhenUnpluggingChanged(boolean keepDreaming); + default void onKeepDreamingWhenUnpluggingChanged(boolean keepDreaming) { + } + + /** + * Called when dreaming has started. + */ + default void onDreamingStarted() { + } + + /** + * Called when dreaming has stopped. + */ + default void onDreamingStopped() { + } } } diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java index de10b1b19a33..6d70d21e3b84 100644 --- a/services/core/java/com/android/server/dreams/DreamController.java +++ b/services/core/java/com/android/server/dreams/DreamController.java @@ -345,6 +345,7 @@ final class DreamController { if (!mCurrentDream.mIsPreviewMode && !mSentStartBroadcast) { mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL, null /* receiverPermission */, mDreamingStartedStoppedOptions); + mListener.onDreamStarted(mCurrentDream.mToken); mSentStartBroadcast = true; } } @@ -353,6 +354,7 @@ final class DreamController { * Callback interface to be implemented by the {@link DreamManagerService}. */ public interface Listener { + void onDreamStarted(Binder token); void onDreamStopped(Binder token); } diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index 0e26d4661017..d2dcc508d01f 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -84,6 +84,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Consumer; /** * Service api for managing dreams. @@ -341,10 +342,24 @@ public final class DreamManagerService extends SystemService { } private void reportKeepDreamingWhenUnpluggingChanged(boolean keepDreaming) { + notifyDreamStateListeners( + listener -> listener.onKeepDreamingWhenUnpluggingChanged(keepDreaming)); + } + + private void reportDreamingStarted() { + notifyDreamStateListeners(listener -> listener.onDreamingStarted()); + } + + private void reportDreamingStopped() { + notifyDreamStateListeners(listener -> listener.onDreamingStopped()); + } + + private void notifyDreamStateListeners( + Consumer<DreamManagerInternal.DreamManagerStateListener> notifier) { mHandler.post(() -> { for (DreamManagerInternal.DreamManagerStateListener listener : mDreamManagerStateListeners) { - listener.onKeepDreamingWhenUnpluggingChanged(keepDreaming); + notifier.accept(listener); } }); } @@ -767,12 +782,23 @@ public final class DreamManagerService extends SystemService { private final DreamController.Listener mControllerListener = new DreamController.Listener() { @Override + public void onDreamStarted(Binder token) { + // Note that this event is distinct from DreamManagerService#startDreamLocked as it + // tracks the DreamService attach point from DreamController, closest to the broadcast + // of ACTION_DREAMING_STARTED. + + reportDreamingStarted(); + } + + @Override public void onDreamStopped(Binder token) { synchronized (mLock) { if (mCurrentDream != null && mCurrentDream.token == token) { cleanupDreamLocked(); } } + + reportDreamingStopped(); } }; diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index fc6b4e9dcb20..38c2be83f070 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -2186,12 +2186,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { Intent.EXTRA_DOCK_STATE_UNDOCKED)); } - // register for dream-related broadcasts - filter = new IntentFilter(); - filter.addAction(Intent.ACTION_DREAMING_STARTED); - filter.addAction(Intent.ACTION_DREAMING_STOPPED); - mContext.registerReceiver(mDreamReceiver, filter); - // register for multiuser-relevant broadcasts filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); mContext.registerReceiver(mMultiuserReceiver, filter); @@ -4774,21 +4768,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }; - BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { - if (mKeyguardDelegate != null) { - mKeyguardDelegate.onDreamingStarted(); - } - } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { - if (mKeyguardDelegate != null) { - mKeyguardDelegate.onDreamingStopped(); - } - } - } - }; - BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java index 646dc4e98c39..495e239d4cd7 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java @@ -18,6 +18,7 @@ import android.os.IBinder; import android.os.PowerManager; import android.os.RemoteException; import android.os.UserHandle; +import android.service.dreams.DreamManagerInternal; import android.util.Log; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -27,6 +28,7 @@ import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IKeyguardDrawnCallback; import com.android.internal.policy.IKeyguardExitCallback; import com.android.internal.policy.IKeyguardService; +import com.android.server.LocalServices; import com.android.server.UiThread; import com.android.server.policy.WindowManagerPolicy.OnKeyguardExitResult; import com.android.server.wm.EventLogTags; @@ -60,6 +62,19 @@ public class KeyguardServiceDelegate { private DrawnListener mDrawnListenerWhenConnect; + private final DreamManagerInternal.DreamManagerStateListener mDreamManagerStateListener = + new DreamManagerInternal.DreamManagerStateListener() { + @Override + public void onDreamingStarted() { + KeyguardServiceDelegate.this.onDreamingStarted(); + } + + @Override + public void onDreamingStopped() { + KeyguardServiceDelegate.this.onDreamingStopped(); + } + }; + private static final class KeyguardState { KeyguardState() { reset(); @@ -158,6 +173,11 @@ public class KeyguardServiceDelegate { } else { if (DEBUG) Log.v(TAG, "*** Keyguard started"); } + + final DreamManagerInternal dreamManager = + LocalServices.getService(DreamManagerInternal.class); + + dreamManager.registerDreamManagerStateListener(mDreamManagerStateListener); } private final ServiceConnection mKeyguardConnection = new ServiceConnection() { diff --git a/services/tests/servicestests/src/com/android/server/dreams/DreamControllerTest.java b/services/tests/servicestests/src/com/android/server/dreams/DreamControllerTest.java index 1ef11974292b..d5ad815d3cdb 100644 --- a/services/tests/servicestests/src/com/android/server/dreams/DreamControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/dreams/DreamControllerTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.ActivityTaskManager; import android.content.ComponentName; import android.content.Context; import android.content.ServiceConnection; @@ -54,6 +55,10 @@ public class DreamControllerTest { private DreamController.Listener mListener; @Mock private Context mContext; + + @Mock + private ActivityTaskManager mActivityTaskManager; + @Mock private IBinder mIBinder; @Mock @@ -80,6 +85,10 @@ public class DreamControllerTest { when(mIDreamService.asBinder()).thenReturn(mIBinder); when(mIBinder.queryLocalInterface(anyString())).thenReturn(mIDreamService); when(mContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true); + when(mContext.getSystemService(Context.ACTIVITY_TASK_SERVICE)) + .thenReturn(mActivityTaskManager); + when(mContext.getSystemServiceName(ActivityTaskManager.class)) + .thenReturn(Context.ACTIVITY_TASK_SERVICE); mToken = new Binder(); mDreamName = ComponentName.unflattenFromString("dream"); @@ -104,6 +113,37 @@ public class DreamControllerTest { } @Test + public void startDream_dreamListenerNotified() { + // Call dream controller to start dreaming. + mDreamController.startDream(mToken, mDreamName, false /*isPreview*/, false /*doze*/, + 0 /*userId*/, null /*wakeLock*/, mOverlayName, "test" /*reason*/); + + // Mock service connected. + final ServiceConnection serviceConnection = captureServiceConnection(); + serviceConnection.onServiceConnected(mDreamName, mIBinder); + mLooper.dispatchAll(); + + // Verify that dream service is called to attach. + verify(mListener).onDreamStarted(any()); + } + + @Test + public void stopDream_dreamListenerNotified() { + // Start dream. + mDreamController.startDream(mToken, mDreamName, false /*isPreview*/, false /*doze*/, + 0 /*userId*/, null /*wakeLock*/, mOverlayName, "test" /*reason*/); + captureServiceConnection().onServiceConnected(mDreamName, mIBinder); + mLooper.dispatchAll(); + + // Stop dream. + mDreamController.stopDream(true /*immediate*/, "test stop dream" /*reason*/); + mLooper.dispatchAll(); + + // Verify that dream service is called to detach. + verify(mListener).onDreamStopped(any()); + } + + @Test public void startDream_attachOnServiceConnectedInPreviewMode() throws RemoteException { // Call dream controller to start dreaming. mDreamController.startDream(mToken, mDreamName, true /*isPreview*/, false /*doze*/, |