1 /*
2  * Copyright (C) 2021 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 package com.android.car.rotary;
17 
18 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
19 import static android.view.accessibility.AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
20 
21 import static org.mockito.Mockito.any;
22 import static org.mockito.Mockito.doAnswer;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.when;
25 
26 import android.graphics.Rect;
27 import android.view.Display;
28 import android.view.accessibility.AccessibilityNodeInfo;
29 import android.view.accessibility.AccessibilityWindowInfo;
30 
31 import androidx.annotation.Nullable;
32 
33 /**
34  * A builder which builds a mock {@link AccessibilityWindowInfo}. Unlike real windows, mock windows
35  * don't need to be recycled.
36  */
37 class WindowBuilder {
38     /** The ID of the window. */
39     private int mId = UNDEFINED_WINDOW_ID;
40     /** The root node in the window's hierarchy. */
41     private AccessibilityNodeInfo mRoot;
42     /** The bounds of this window in the screen. */
43     private Rect mBoundsInScreen;
44     /** The window type, if specified. */
45     private int mType;
46     /** Whether the window is focused. */
47     private boolean mFocused = false;
48     /** The display ID, if specified. */
49     private int mDisplayId = Display.DEFAULT_DISPLAY;
50     /** The task ID, if specified. */
51     private int mTaskId = INVALID_TASK_ID;
52 
build()53     AccessibilityWindowInfo build() {
54         AccessibilityWindowInfo window = mock(AccessibilityWindowInfo.class);
55         when(window.getId()).thenReturn(mId);
56         when(window.getRoot())
57                 .thenReturn(MockNodeCopierProvider.get().copy(mRoot))
58                 .thenReturn(MockNodeCopierProvider.get().copy(mRoot))
59                 .thenReturn(MockNodeCopierProvider.get().copy(mRoot))
60                 .thenReturn(MockNodeCopierProvider.get().copy(mRoot))
61                 .thenReturn(MockNodeCopierProvider.get().copy(mRoot))
62                 .thenReturn(MockNodeCopierProvider.get().copy(mRoot))
63                 .thenThrow(new RuntimeException(
64                         "Exceeded the maximum calls. Please add more parameters"));
65         if (mBoundsInScreen != null) {
66             // Mock AccessibilityWindowInfo#getBoundsInScreen(Rect).
67             doAnswer(invocation -> {
68                 Object[] args = invocation.getArguments();
69                 ((Rect) args[0]).set(mBoundsInScreen);
70                 return null;
71             }).when(window).getBoundsInScreen(any(Rect.class));
72         }
73         when(window.getType()).thenReturn(mType);
74         when(window.isFocused()).thenReturn(mFocused);
75         when(window.getDisplayId()).thenReturn(mDisplayId);
76         when(window.getTaskId()).thenReturn(mTaskId);
77         return window;
78     }
79 
setId(int id)80     WindowBuilder setId(int id) {
81         mId = id;
82         return this;
83     }
84 
setRoot(@ullable AccessibilityNodeInfo root)85     WindowBuilder setRoot(@Nullable AccessibilityNodeInfo root) {
86         mRoot = MockNodeCopierProvider.get().copy(root);
87         return this;
88     }
89 
setBoundsInScreen(@ullable Rect boundsInScreen)90     WindowBuilder setBoundsInScreen(@Nullable Rect boundsInScreen) {
91         mBoundsInScreen = boundsInScreen;
92         return this;
93     }
94 
setType(int type)95     WindowBuilder setType(int type) {
96         mType = type;
97         return this;
98     }
99 
setFocused(boolean isFocused)100     WindowBuilder setFocused(boolean isFocused) {
101         mFocused = isFocused;
102         return this;
103     }
104 
setDisplayId(int displayId)105     WindowBuilder setDisplayId(int displayId) {
106         mDisplayId = displayId;
107         return this;
108     }
109 
setTaskId(int taskId)110     WindowBuilder setTaskId(int taskId) {
111         mTaskId = taskId;
112         return this;
113     }
114 }
115