1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.reardisplay;
18 
19 import static junit.framework.Assert.assertEquals;
20 import static junit.framework.Assert.assertNotSame;
21 
22 import static org.mockito.ArgumentMatchers.anyBoolean;
23 import static org.mockito.ArgumentMatchers.anyLong;
24 import static org.mockito.Mockito.reset;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.when;
27 
28 import android.content.res.Configuration;
29 import android.content.res.Resources;
30 import android.hardware.devicestate.DeviceState;
31 import android.hardware.devicestate.DeviceStateManager;
32 import android.testing.TestableLooper;
33 import android.view.LayoutInflater;
34 import android.view.View;
35 import android.widget.TextView;
36 
37 import androidx.test.ext.junit.runners.AndroidJUnit4;
38 import androidx.test.filters.SmallTest;
39 
40 import com.android.systemui.SysuiTestCase;
41 import com.android.systemui.flags.FakeFeatureFlags;
42 import com.android.systemui.model.SysUiState;
43 import com.android.systemui.res.R;
44 import com.android.systemui.statusbar.CommandQueue;
45 import com.android.systemui.statusbar.phone.SystemUIDialog;
46 import com.android.systemui.util.concurrency.FakeExecutor;
47 import com.android.systemui.util.time.FakeSystemClock;
48 
49 import org.junit.Before;
50 import org.junit.Test;
51 import org.junit.runner.RunWith;
52 import org.mockito.ArgumentCaptor;
53 import org.mockito.Mock;
54 import org.mockito.MockitoAnnotations;
55 
56 @SmallTest
57 @RunWith(AndroidJUnit4.class)
58 @TestableLooper.RunWithLooper(setAsMainLooper = true)
59 public class RearDisplayDialogControllerTest extends SysuiTestCase {
60 
61     @Mock
62     private CommandQueue mCommandQueue;
63     @Mock
64     private SystemUIDialog.Factory mSystemUIDialogFactory;
65     @Mock
66     private SystemUIDialog mSystemUIDialog;
67     private final FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
68     @Mock
69     private SysUiState mSysUiState;
70     @Mock
71     private Resources mResources;
72 
73     LayoutInflater mLayoutInflater = LayoutInflater.from(mContext);
74 
75     private final FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
76 
77     private static final int CLOSED_BASE_STATE = 0;
78     private static final int OPEN_BASE_STATE = 1;
79 
80     @Before
setup()81     public void setup() {
82         MockitoAnnotations.initMocks(this);
83 
84         when(mSysUiState.setFlag(anyLong(), anyBoolean())).thenReturn(mSysUiState);
85         when(mSystemUIDialogFactory.create()).thenReturn(mSystemUIDialog);
86         when(mSystemUIDialog.getContext()).thenReturn(mContext);
87     }
88     @Test
testClosedDialogIsShown()89     public void testClosedDialogIsShown() {
90         RearDisplayDialogController controller = new RearDisplayDialogController(
91                 mCommandQueue,
92                 mFakeExecutor,
93                 mResources,
94                 mLayoutInflater,
95                 mSystemUIDialogFactory);
96         controller.setDeviceStateManagerCallback(new TestDeviceStateManagerCallback());
97         controller.setFoldedStates(new int[]{0});
98         controller.setAnimationRepeatCount(0);
99 
100         controller.showRearDisplayDialog(CLOSED_BASE_STATE);
101         verify(mSystemUIDialog).show();
102 
103         View container = getDialogViewContainer();
104         TextView deviceClosedTitleTextView = container.findViewById(
105                 R.id.rear_display_title_text_view);
106         assertEquals(deviceClosedTitleTextView.getText().toString(),
107                 getContext().getResources().getString(
108                         R.string.rear_display_folded_bottom_sheet_title));
109     }
110 
111     @Test
testClosedDialogIsRefreshedOnConfigurationChange()112     public void testClosedDialogIsRefreshedOnConfigurationChange() {
113         RearDisplayDialogController controller = new RearDisplayDialogController(
114                 mCommandQueue,
115                 mFakeExecutor,
116                 mResources,
117                 mLayoutInflater,
118                 mSystemUIDialogFactory);
119         controller.setDeviceStateManagerCallback(new TestDeviceStateManagerCallback());
120         controller.setFoldedStates(new int[]{0});
121         controller.setAnimationRepeatCount(0);
122 
123         controller.showRearDisplayDialog(CLOSED_BASE_STATE);
124         verify(mSystemUIDialog).show();
125         View container = getDialogViewContainer();
126         TextView deviceClosedTitleTextView = container.findViewById(
127                 R.id.rear_display_title_text_view);
128 
129         reset(mSystemUIDialog);
130         when(mSystemUIDialog.isShowing()).thenReturn(true);
131         when(mSystemUIDialog.getContext()).thenReturn(mContext);
132 
133         controller.onConfigChanged(new Configuration());
134         TextView deviceClosedTitleTextView2 = container.findViewById(
135                 R.id.rear_display_title_text_view);
136 
137         assertNotSame(deviceClosedTitleTextView, deviceClosedTitleTextView2);
138     }
139 
140     @Test
testOpenDialogIsShown()141     public void testOpenDialogIsShown() {
142         RearDisplayDialogController controller = new RearDisplayDialogController(
143                 mCommandQueue,
144                 mFakeExecutor,
145                 mResources,
146                 mLayoutInflater,
147                 mSystemUIDialogFactory);
148         controller.setDeviceStateManagerCallback(new TestDeviceStateManagerCallback());
149         controller.setFoldedStates(new int[]{0});
150         controller.setAnimationRepeatCount(0);
151 
152         controller.showRearDisplayDialog(OPEN_BASE_STATE);
153 
154         verify(mSystemUIDialog).show();
155         View container = getDialogViewContainer();
156         TextView deviceClosedTitleTextView = container.findViewById(
157                 R.id.rear_display_title_text_view);
158         assertEquals(deviceClosedTitleTextView.getText().toString(),
159                 getContext().getResources().getString(
160                         R.string.rear_display_unfolded_bottom_sheet_title));
161     }
162 
getDialogViewContainer()163     private View getDialogViewContainer() {
164         ArgumentCaptor<View> viewCaptor = ArgumentCaptor.forClass(View.class);
165         verify(mSystemUIDialog).setView(viewCaptor.capture());
166 
167         return viewCaptor.getValue();
168     }
169     /**
170      * Empty device state manager callbacks, so we can verify that the correct
171      * dialogs are being created regardless of device state of the test device.
172      */
173     private static class TestDeviceStateManagerCallback implements
174             DeviceStateManager.DeviceStateCallback {
175 
176         @Override
onDeviceStateChanged(DeviceState state)177         public void onDeviceStateChanged(DeviceState state) { }
178     }
179 }
180