Merge changes Idd362f88,Ifb1e1266 into udc-dev

* changes:
  Use KeyguardUpdateMonitor in DreamCondition.
  Send dream state updates through DreamManagerStateListener.
This commit is contained in:
Bryce Lee
2023-04-21 14:54:16 +00:00
committed by Android (Google) Code Review
8 changed files with 137 additions and 67 deletions

View File

@@ -84,6 +84,19 @@ public abstract class DreamManagerInternal {
* *
* @param keepDreaming True if the current dream should continue when undocking. * @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() {
}
} }
} }

View File

@@ -16,12 +16,9 @@
package com.android.systemui.dreams.conditions; package com.android.systemui.dreams.conditions;
import android.app.DreamManager; import android.app.DreamManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.text.TextUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.shared.condition.Condition; import com.android.systemui.shared.condition.Condition;
import javax.inject.Inject; import javax.inject.Inject;
@@ -30,48 +27,33 @@ import javax.inject.Inject;
* {@link DreamCondition} provides a signal when a dream begins and ends. * {@link DreamCondition} provides a signal when a dream begins and ends.
*/ */
public class DreamCondition extends Condition { public class DreamCondition extends Condition {
private final Context mContext;
private final DreamManager mDreamManager; private final DreamManager mDreamManager;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() { private final KeyguardUpdateMonitor mUpdateMonitor;
@Override
public void onReceive(Context context, Intent intent) {
processIntent(intent); private final KeyguardUpdateMonitorCallback mUpdateCallback =
} new KeyguardUpdateMonitorCallback() {
}; @Override
public void onDreamingStateChanged(boolean dreaming) {
updateCondition(dreaming);
}
};
@Inject @Inject
public DreamCondition(Context context, public DreamCondition(DreamManager dreamManager, KeyguardUpdateMonitor monitor) {
DreamManager dreamManager) {
mContext = context;
mDreamManager = dreamManager; mDreamManager = dreamManager;
} mUpdateMonitor = monitor;
private void processIntent(Intent intent) {
// In the case of a non-existent sticky broadcast, ignore when there is no intent.
if (intent == null) {
return;
}
if (TextUtils.equals(intent.getAction(), Intent.ACTION_DREAMING_STARTED)) {
updateCondition(true);
} else if (TextUtils.equals(intent.getAction(), Intent.ACTION_DREAMING_STOPPED)) {
updateCondition(false);
} else {
throw new IllegalStateException("unexpected intent:" + intent);
}
} }
@Override @Override
protected void start() { protected void start() {
final IntentFilter filter = new IntentFilter(); mUpdateMonitor.registerCallback(mUpdateCallback);
filter.addAction(Intent.ACTION_DREAMING_STARTED);
filter.addAction(Intent.ACTION_DREAMING_STOPPED);
mContext.registerReceiver(mReceiver, filter);
updateCondition(mDreamManager.isDreaming()); updateCondition(mDreamManager.isDreaming());
} }
@Override @Override
protected void stop() { protected void stop() {
mContext.unregisterReceiver(mReceiver); mUpdateMonitor.removeCallback(mUpdateCallback);
} }
} }

View File

@@ -18,7 +18,6 @@ package com.android.systemui.dreams.conditions;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
@@ -26,13 +25,13 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.DreamManager; import android.app.DreamManager;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.shared.condition.Condition; import com.android.systemui.shared.condition.Condition;
@@ -55,6 +54,9 @@ public class DreamConditionTest extends SysuiTestCase {
@Mock @Mock
DreamManager mDreamManager; DreamManager mDreamManager;
@Mock
KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Before @Before
public void setup() { public void setup() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
@@ -66,7 +68,7 @@ public class DreamConditionTest extends SysuiTestCase {
@Test @Test
public void testInitialDreamingState() { public void testInitialDreamingState() {
when(mDreamManager.isDreaming()).thenReturn(true); when(mDreamManager.isDreaming()).thenReturn(true);
final DreamCondition condition = new DreamCondition(mContext, mDreamManager); final DreamCondition condition = new DreamCondition(mDreamManager, mKeyguardUpdateMonitor);
condition.addCallback(mCallback); condition.addCallback(mCallback);
verify(mCallback).onConditionChanged(eq(condition)); verify(mCallback).onConditionChanged(eq(condition));
@@ -79,7 +81,7 @@ public class DreamConditionTest extends SysuiTestCase {
@Test @Test
public void testInitialNonDreamingState() { public void testInitialNonDreamingState() {
when(mDreamManager.isDreaming()).thenReturn(false); when(mDreamManager.isDreaming()).thenReturn(false);
final DreamCondition condition = new DreamCondition(mContext, mDreamManager); final DreamCondition condition = new DreamCondition(mDreamManager, mKeyguardUpdateMonitor);
condition.addCallback(mCallback); condition.addCallback(mCallback);
verify(mCallback, never()).onConditionChanged(eq(condition)); verify(mCallback, never()).onConditionChanged(eq(condition));
@@ -91,15 +93,21 @@ public class DreamConditionTest extends SysuiTestCase {
*/ */
@Test @Test
public void testChange() { public void testChange() {
final ArgumentCaptor<BroadcastReceiver> receiverCaptor = final ArgumentCaptor<KeyguardUpdateMonitorCallback> callbackCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class); ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
when(mDreamManager.isDreaming()).thenReturn(true); when(mDreamManager.isDreaming()).thenReturn(true);
final DreamCondition condition = new DreamCondition(mContext, mDreamManager); final DreamCondition condition = new DreamCondition(mDreamManager, mKeyguardUpdateMonitor);
condition.addCallback(mCallback); condition.addCallback(mCallback);
verify(mContext).registerReceiver(receiverCaptor.capture(), any()); verify(mKeyguardUpdateMonitor).registerCallback(callbackCaptor.capture());
clearInvocations(mCallback); clearInvocations(mCallback);
receiverCaptor.getValue().onReceive(mContext, new Intent(Intent.ACTION_DREAMING_STOPPED)); callbackCaptor.getValue().onDreamingStateChanged(false);
verify(mCallback).onConditionChanged(eq(condition)); verify(mCallback).onConditionChanged(eq(condition));
assertThat(condition.isConditionMet()).isFalse(); assertThat(condition.isConditionMet()).isFalse();
clearInvocations(mCallback);
callbackCaptor.getValue().onDreamingStateChanged(true);
verify(mCallback).onConditionChanged(eq(condition));
assertThat(condition.isConditionMet()).isTrue();
} }
} }

View File

@@ -345,6 +345,7 @@ final class DreamController {
if (!mCurrentDream.mIsPreviewMode && !mSentStartBroadcast) { if (!mCurrentDream.mIsPreviewMode && !mSentStartBroadcast) {
mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL, mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL,
null /* receiverPermission */, mDreamingStartedStoppedOptions); null /* receiverPermission */, mDreamingStartedStoppedOptions);
mListener.onDreamStarted(mCurrentDream.mToken);
mSentStartBroadcast = true; mSentStartBroadcast = true;
} }
} }
@@ -353,6 +354,7 @@ final class DreamController {
* Callback interface to be implemented by the {@link DreamManagerService}. * Callback interface to be implemented by the {@link DreamManagerService}.
*/ */
public interface Listener { public interface Listener {
void onDreamStarted(Binder token);
void onDreamStopped(Binder token); void onDreamStopped(Binder token);
} }

View File

@@ -84,6 +84,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
/** /**
* Service api for managing dreams. * Service api for managing dreams.
@@ -341,10 +342,24 @@ public final class DreamManagerService extends SystemService {
} }
private void reportKeepDreamingWhenUnpluggingChanged(boolean keepDreaming) { 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(() -> { mHandler.post(() -> {
for (DreamManagerInternal.DreamManagerStateListener listener for (DreamManagerInternal.DreamManagerStateListener listener
: mDreamManagerStateListeners) { : mDreamManagerStateListeners) {
listener.onKeepDreamingWhenUnpluggingChanged(keepDreaming); notifier.accept(listener);
} }
}); });
} }
@@ -766,6 +781,15 @@ public final class DreamManagerService extends SystemService {
} }
private final DreamController.Listener mControllerListener = new DreamController.Listener() { 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 @Override
public void onDreamStopped(Binder token) { public void onDreamStopped(Binder token) {
synchronized (mLock) { synchronized (mLock) {
@@ -773,6 +797,8 @@ public final class DreamManagerService extends SystemService {
cleanupDreamLocked(); cleanupDreamLocked();
} }
} }
reportDreamingStopped();
} }
}; };

View File

@@ -2186,12 +2186,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Intent.EXTRA_DOCK_STATE_UNDOCKED)); 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 // register for multiuser-relevant broadcasts
filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(mMultiuserReceiver, filter); mContext.registerReceiver(mMultiuserReceiver, filter);
@@ -4785,21 +4779,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() { BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {

View File

@@ -18,6 +18,7 @@ import android.os.IBinder;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
import android.service.dreams.DreamManagerInternal;
import android.util.Log; import android.util.Log;
import android.util.Slog; import android.util.Slog;
import android.util.proto.ProtoOutputStream; 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.IKeyguardDrawnCallback;
import com.android.internal.policy.IKeyguardExitCallback; import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService; import com.android.internal.policy.IKeyguardService;
import com.android.server.LocalServices;
import com.android.server.UiThread; import com.android.server.UiThread;
import com.android.server.policy.WindowManagerPolicy.OnKeyguardExitResult; import com.android.server.policy.WindowManagerPolicy.OnKeyguardExitResult;
import com.android.server.wm.EventLogTags; import com.android.server.wm.EventLogTags;
@@ -60,6 +62,19 @@ public class KeyguardServiceDelegate {
private DrawnListener mDrawnListenerWhenConnect; 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 { private static final class KeyguardState {
KeyguardState() { KeyguardState() {
reset(); reset();
@@ -158,6 +173,11 @@ public class KeyguardServiceDelegate {
} else { } else {
if (DEBUG) Log.v(TAG, "*** Keyguard started"); if (DEBUG) Log.v(TAG, "*** Keyguard started");
} }
final DreamManagerInternal dreamManager =
LocalServices.getService(DreamManagerInternal.class);
dreamManager.registerDreamManagerStateListener(mDreamManagerStateListener);
} }
private final ServiceConnection mKeyguardConnection = new ServiceConnection() { private final ServiceConnection mKeyguardConnection = new ServiceConnection() {

View File

@@ -25,6 +25,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.ActivityTaskManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.ServiceConnection; import android.content.ServiceConnection;
@@ -54,6 +55,10 @@ public class DreamControllerTest {
private DreamController.Listener mListener; private DreamController.Listener mListener;
@Mock @Mock
private Context mContext; private Context mContext;
@Mock
private ActivityTaskManager mActivityTaskManager;
@Mock @Mock
private IBinder mIBinder; private IBinder mIBinder;
@Mock @Mock
@@ -80,6 +85,10 @@ public class DreamControllerTest {
when(mIDreamService.asBinder()).thenReturn(mIBinder); when(mIDreamService.asBinder()).thenReturn(mIBinder);
when(mIBinder.queryLocalInterface(anyString())).thenReturn(mIDreamService); when(mIBinder.queryLocalInterface(anyString())).thenReturn(mIDreamService);
when(mContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true); 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(); mToken = new Binder();
mDreamName = ComponentName.unflattenFromString("dream"); mDreamName = ComponentName.unflattenFromString("dream");
@@ -103,6 +112,37 @@ public class DreamControllerTest {
eq(false) /*preview*/, any()); eq(false) /*preview*/, any());
} }
@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 @Test
public void startDream_attachOnServiceConnectedInPreviewMode() throws RemoteException { public void startDream_attachOnServiceConnectedInPreviewMode() throws RemoteException {
// Call dream controller to start dreaming. // Call dream controller to start dreaming.