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 
17 package android.server.wm.jetpack.utils;
18 
19 import static android.server.wm.jetpack.extensions.util.SidecarUtil.getSidecarInterface;
20 import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getActivityWindowToken;
21 import static com.google.common.truth.Truth.assertThat;
22 import static org.junit.Assert.assertEquals;
23 
24 import android.os.Bundle;
25 import android.os.IBinder;
26 import android.view.View;
27 
28 import androidx.annotation.NonNull;
29 import androidx.annotation.Nullable;
30 import androidx.window.sidecar.SidecarDisplayFeature;
31 import androidx.window.sidecar.SidecarInterface;
32 import androidx.window.sidecar.SidecarWindowLayoutInfo;
33 
34 import java.util.HashSet;
35 import java.util.Set;
36 import java.util.stream.Collectors;
37 
38 /**
39  * Activity that can verify the return value of
40  * {@link SidecarInterface#getWindowLayoutInfo(IBinder)} on activity's different states.
41  */
42 // TODO (b/201119421) - explore moving the assert logic out from here and into the calling test
43 public class TestGetWindowLayoutInfoActivity extends TestActivity {
44 
45     private SidecarInterface mSidecarInterface;
46     @Nullable private SidecarWindowLayoutInfo mPrevWindowLayoutInfo;
47 
48     @Override
onCreate(@ullable Bundle savedInstanceState)49     public void onCreate(@Nullable Bundle savedInstanceState) {
50         super.onCreate(savedInstanceState);
51         mSidecarInterface = getSidecarInterface(this);
52         assertCorrectWindowLayoutInfoOrException(true /* isOkToThrowException */);
53     }
54 
55     @Override
onAttachedToWindow()56     public void onAttachedToWindow() {
57         super.onAttachedToWindow();
58         assertCorrectWindowLayoutInfoOrException(true /* isOkToThrowException */);
59     }
60 
61     @Override
onResume()62     protected void onResume() {
63         super.onResume();
64         assertCorrectWindowLayoutInfoOrException(true /* isOkToThrowException */);
65     }
66 
67     @Override
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)68     public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
69             int oldTop, int oldRight, int oldBottom) {
70         super.onLayoutChange(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom);
71         assertCorrectWindowLayoutInfoOrException(false /* isOkToThrowException */);
72     }
73 
74     @Override
onDestroy()75     public void onDestroy() {
76         super.onDestroy();
77     }
78 
assertCorrectWindowLayoutInfoOrException(boolean isOkToThrowException)79     private void assertCorrectWindowLayoutInfoOrException(boolean isOkToThrowException) {
80         IBinder windowToken = getActivityWindowToken(this);
81         if (windowToken == null) {
82             return;
83         }
84 
85         SidecarWindowLayoutInfo windowLayoutInfo = null;
86         try {
87             windowLayoutInfo = mSidecarInterface.getWindowLayoutInfo(windowToken);
88         } catch (Exception e) {
89             assertThat(isOkToThrowException).isTrue();
90         }
91 
92         if (mPrevWindowLayoutInfo == null) {
93             mPrevWindowLayoutInfo = windowLayoutInfo;
94         } else {
95             assertEqualWindowLayoutInfo(mPrevWindowLayoutInfo, windowLayoutInfo);
96         }
97     }
98 
99     private static class SidecarDisplayFeatureComparisonWrapper {
100 
101         private SidecarDisplayFeature mFeature;
102 
SidecarDisplayFeatureComparisonWrapper( @onNull SidecarDisplayFeature feature)103         private SidecarDisplayFeatureComparisonWrapper(
104                 @NonNull SidecarDisplayFeature feature) {
105             mFeature = feature;
106         }
107 
create( @onNull SidecarDisplayFeature feature)108         public static SidecarDisplayFeatureComparisonWrapper create(
109                 @NonNull SidecarDisplayFeature feature) {
110             return new SidecarDisplayFeatureComparisonWrapper(feature);
111         }
112 
113         @Override
equals(Object o)114         public boolean equals(Object o) {
115             if (o == this) {
116                 return true;
117             }
118             if (!(o instanceof SidecarDisplayFeatureComparisonWrapper)) {
119                 return false;
120             }
121             SidecarDisplayFeatureComparisonWrapper other
122                     = (SidecarDisplayFeatureComparisonWrapper) o;
123             return mFeature.getRect().equals(other.mFeature.getRect())
124                     && mFeature.getType() == other.mFeature.getType();
125         }
126 
127         @Override
hashCode()128         public final int hashCode() {
129             int result = mFeature.getRect().hashCode();
130             result = 31 * result + mFeature.getType();
131             return result;
132         }
133     }
134 
assertEqualWindowLayoutInfo(SidecarWindowLayoutInfo info1, SidecarWindowLayoutInfo info2)135     private void assertEqualWindowLayoutInfo(SidecarWindowLayoutInfo info1,
136             SidecarWindowLayoutInfo info2) {
137         // If neither has any display features, then they are equal
138         if (info1.displayFeatures == null && info2.displayFeatures == null) {
139             return;
140         }
141         // Convert display features into comparable display features
142         Set<SidecarDisplayFeatureComparisonWrapper> displayFeatures1 = collectDisplayFeatures(
143                 info1);
144         Set<SidecarDisplayFeatureComparisonWrapper> displayFeatures2 = collectDisplayFeatures(
145                 info2);
146         assertEquals(displayFeatures1, displayFeatures2);
147     }
148 
collectDisplayFeatures( @onNull SidecarWindowLayoutInfo info)149     private Set<SidecarDisplayFeatureComparisonWrapper> collectDisplayFeatures(
150             @NonNull SidecarWindowLayoutInfo info) {
151         if (info.displayFeatures == null) {
152             return new HashSet<SidecarDisplayFeatureComparisonWrapper>();
153         }
154         return info.displayFeatures
155                 .stream()
156                 .map(SidecarDisplayFeatureComparisonWrapper::create)
157                 .collect(Collectors.toSet());
158     }
159 }
160