summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/AlertDialogWithDelegateTest.kt61
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AlertDialogWithDelegate.kt64
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DialogDelegate.kt48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java63
5 files changed, 226 insertions, 49 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/AlertDialogWithDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/AlertDialogWithDelegateTest.kt
new file mode 100644
index 000000000000..5389fc29eaf1
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/AlertDialogWithDelegateTest.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 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.systemui.statusbar.phone
+
+import android.app.AlertDialog
+import android.content.res.Configuration
+import android.testing.TestableLooper.RunWithLooper
+import android.view.WindowManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.res.R
+import com.android.systemui.util.mockito.mock
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito
+
+@RunWith(AndroidJUnit4::class)
+@RunWithLooper
+@SmallTest
+class AlertDialogWithDelegateTest : SysuiTestCase() {
+
+ private val delegate = mock<DialogDelegate<AlertDialog>>()
+
+ @Test
+ fun delegateIsCalled_inCorrectOrder() {
+ val configuration = Configuration()
+ val inOrder = Mockito.inOrder(delegate)
+ val dialog = createDialog()
+
+ dialog.show()
+ dialog.onWindowFocusChanged(/* hasFocus= */ true)
+ dialog.onConfigurationChanged(configuration)
+ dialog.dismiss()
+
+ inOrder.verify(delegate).beforeCreate(dialog, /* savedInstanceState= */ null)
+ inOrder.verify(delegate).onCreate(dialog, /* savedInstanceState= */ null)
+ inOrder.verify(delegate).onStart(dialog)
+ inOrder.verify(delegate).onWindowFocusChanged(dialog, /* hasFocus= */ true)
+ inOrder.verify(delegate).onConfigurationChanged(dialog, configuration)
+ inOrder.verify(delegate).onStop(dialog)
+ }
+
+ private fun createDialog(): AlertDialogWithDelegate =
+ AlertDialogWithDelegate(context, R.style.Theme_SystemUI_Dialog, delegate).apply {
+ window?.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL)
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java
index 162008808791..0b922a844690 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java
@@ -29,22 +29,28 @@ import static org.mockito.Mockito.when;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Configuration;
import android.testing.TestableLooper.RunWithLooper;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
+import com.android.systemui.model.SysUiState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
+import org.mockito.InOrder;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -58,6 +64,8 @@ public class SystemUIDialogTest extends SysuiTestCase {
private FeatureFlags mFeatureFlags;
@Mock
private BroadcastDispatcher mBroadcastDispatcher;
+ @Mock
+ private DialogDelegate<SystemUIDialog> mDelegate;
@Before
public void setup() {
@@ -143,4 +151,35 @@ public class SystemUIDialogTest extends SysuiTestCase {
assertThat(calledStart.get()).isTrue();
assertThat(calledStop.get()).isTrue();
}
+
+ @Test
+ public void delegateIsCalled_inCorrectOrder() {
+ Configuration configuration = new Configuration();
+ InOrder inOrder = Mockito.inOrder(mDelegate);
+ SystemUIDialog dialog = createDialogWithDelegate();
+
+ dialog.show();
+ dialog.onWindowFocusChanged(/* hasFocus= */ true);
+ dialog.onConfigurationChanged(configuration);
+ dialog.dismiss();
+
+ inOrder.verify(mDelegate).beforeCreate(dialog, /* savedInstanceState= */ null);
+ inOrder.verify(mDelegate).onCreate(dialog, /* savedInstanceState= */ null);
+ inOrder.verify(mDelegate).onStart(dialog);
+ inOrder.verify(mDelegate).onWindowFocusChanged(dialog, /* hasFocus= */ true);
+ inOrder.verify(mDelegate).onConfigurationChanged(dialog, configuration);
+ inOrder.verify(mDelegate).onStop(dialog);
+ }
+
+ private SystemUIDialog createDialogWithDelegate() {
+ SystemUIDialog.Factory factory = new SystemUIDialog.Factory(
+ getContext(),
+ mFeatureFlags,
+ Dependency.get(SystemUIDialogManager.class),
+ Dependency.get(SysUiState.class),
+ Dependency.get(BroadcastDispatcher.class),
+ Dependency.get(DialogLaunchAnimator.class)
+ );
+ return factory.create(mDelegate);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AlertDialogWithDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AlertDialogWithDelegate.kt
new file mode 100644
index 000000000000..6211e1755217
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AlertDialogWithDelegate.kt
@@ -0,0 +1,64 @@
+/*
+ * 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.systemui.statusbar.phone
+
+import android.app.AlertDialog
+import android.content.Context
+import android.content.res.Configuration
+import android.os.Bundle
+import android.view.ViewRootImpl
+import android.view.ViewRootImpl.ConfigChangedCallback
+import androidx.annotation.StyleRes
+
+/**
+ * Implementation of [AlertDialog] that takes as parameter a [DialogDelegate].
+ *
+ * Can be used when composition is preferred over inheritance.
+ */
+class AlertDialogWithDelegate(
+ context: Context,
+ @StyleRes theme: Int,
+ private val delegate: DialogDelegate<AlertDialog>
+) : AlertDialog(context, theme), ConfigChangedCallback {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ delegate.beforeCreate(dialog = this, savedInstanceState)
+ super.onCreate(savedInstanceState)
+ delegate.onCreate(dialog = this, savedInstanceState)
+ }
+
+ override fun onConfigurationChanged(configuration: Configuration) {
+ delegate.onConfigurationChanged(dialog = this, configuration)
+ }
+
+ override fun onStart() {
+ super.onStart()
+ ViewRootImpl.addConfigCallback(this)
+ delegate.onStart(dialog = this)
+ }
+
+ override fun onStop() {
+ super.onStop()
+ ViewRootImpl.removeConfigCallback(this)
+ delegate.onStop(dialog = this)
+ }
+
+ override fun onWindowFocusChanged(hasFocus: Boolean) {
+ super.onWindowFocusChanged(hasFocus)
+ delegate.onWindowFocusChanged(dialog = this, hasFocus)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DialogDelegate.kt
new file mode 100644
index 000000000000..b56baeefda19
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DialogDelegate.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.systemui.statusbar.phone
+
+import android.app.Dialog
+import android.content.res.Configuration
+import android.os.Bundle
+import android.view.ViewRootImpl
+
+/**
+ * A delegate class that should be implemented in place of subclassing [Dialog].
+ *
+ * To use with [SystemUIDialog], implement this interface and then pass an instance of your
+ * implementation to [SystemUIDialog.Factory.create].
+ */
+interface DialogDelegate<T : Dialog> {
+ /** Called before [Dialog.onCreate] is called. */
+ fun beforeCreate(dialog: T, savedInstanceState: Bundle?) {}
+
+ /** Called after [Dialog.onCreate] is called. */
+ fun onCreate(dialog: T, savedInstanceState: Bundle?) {}
+
+ /** Called after [Dialog.onStart] is called. */
+ fun onStart(dialog: T) {}
+
+ /** Called after [Dialog.onStop] is called. */
+ fun onStop(dialog: T) {}
+
+ /** Called after [Dialog.onWindowFocusChanged] is called. */
+ fun onWindowFocusChanged(dialog: T, hasFocus: Boolean) {}
+
+ /** Called as part of [ViewRootImpl.ConfigChangedCallback.onConfigurationChanged]. */
+ fun onConfigurationChanged(dialog: T, configuration: Configuration) {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 2558645e3f64..824de01ca59f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -42,13 +42,13 @@ import android.view.WindowManager.LayoutParams;
import androidx.annotation.Nullable;
import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.res.R;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.util.DialogKt;
@@ -60,7 +60,7 @@ import javax.inject.Inject;
/**
* Class for dialogs that should appear over panels and keyguard.
*
- * DO NOT SUBCLASS THIS. See {@link SystemUIDialog.Delegate} for an interface that enables
+ * DO NOT SUBCLASS THIS. See {@link DialogDelegate} for an interface that enables
* customizing behavior via composition instead of inheritance. Clients should implement the
* Delegate class and then pass their implementation into the SystemUIDialog constructor.
*
@@ -79,7 +79,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
private final Context mContext;
private final FeatureFlags mFeatureFlags;
- private final Delegate mDelegate;
+ private final DialogDelegate<SystemUIDialog> mDelegate;
@Nullable private final DismissReceiver mDismissReceiver;
private final Handler mHandler = new Handler();
private final SystemUIDialogManager mDialogManager;
@@ -110,7 +110,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
Dependency.get(SysUiState.class),
Dependency.get(BroadcastDispatcher.class),
Dependency.get(DialogLaunchAnimator.class),
- new Delegate() {});
+ new DialogDelegate<>() {});
}
@Inject
@@ -129,7 +129,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
sysUiState,
broadcastDispatcher,
dialogLaunchAnimator,
- new Delegate(){});
+ new DialogDelegate<>(){});
}
public static class Factory {
@@ -156,7 +156,11 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
mDialogLaunchAnimator = dialogLaunchAnimator;
}
- public SystemUIDialog create(Delegate delegate) {
+ /**
+ * Creates a new instance of {@link SystemUIDialog} with {@code delegate} as the {@link
+ * DialogDelegate}.
+ */
+ public SystemUIDialog create(DialogDelegate<SystemUIDialog> delegate) {
return new SystemUIDialog(
mContext,
DEFAULT_THEME,
@@ -188,7 +192,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
sysUiState,
broadcastDispatcher,
dialogLaunchAnimator,
- new Delegate(){});
+ new DialogDelegate<>(){});
}
public SystemUIDialog(
@@ -200,7 +204,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
SysUiState sysUiState,
BroadcastDispatcher broadcastDispatcher,
DialogLaunchAnimator dialogLaunchAnimator,
- Delegate delegate) {
+ DialogDelegate<SystemUIDialog> delegate) {
super(context, theme);
mContext = context;
mFeatureFlags = featureFlags;
@@ -309,7 +313,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
* should override this method instead.
*/
protected void start() {
- mDelegate.start(this);
+ mDelegate.onStart(this);
}
@Override
@@ -333,7 +337,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
* should override this method instead.
*/
protected void stop() {
- mDelegate.stop(this);
+ mDelegate.onStop(this);
}
@Override
@@ -584,43 +588,4 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
mDialog.dismiss();
}
}
-
- /**
- * A delegate class that should be implemented in place of sublcassing {@link SystemUIDialog}.
- *
- * Implement this interface and then pass an instance of your implementation to
- * {@link SystemUIDialog.Factory#create(Delegate)}.
- */
- public interface Delegate {
- /**
- * Called before {@link AlertDialog#onCreate} is called.
- */
- default void beforeCreate(SystemUIDialog dialog, Bundle savedInstanceState) {}
-
- /**
- * Called after {@link AlertDialog#onCreate} is called.
- */
- default void onCreate(SystemUIDialog dialog, Bundle savedInstanceState) {}
-
- /**
- * Called after {@link AlertDialog#onStart} is called.
- */
- default void start(SystemUIDialog dialog) {}
-
- /**
- * Called after {@link AlertDialog#onStop} is called.
- */
- default void stop(SystemUIDialog dialog) {}
-
- /**
- * Called after {@link AlertDialog#onWindowFocusChanged(boolean)} is called.
- */
- default void onWindowFocusChanged(SystemUIDialog dialog, boolean hasFocus) {}
-
- /**
- * Called as part of
- * {@link ViewRootImpl.ConfigChangedCallback#onConfigurationChanged(Configuration)}.
- */
- default void onConfigurationChanged(SystemUIDialog dialog, Configuration configuration) {}
- }
}