1 /*
2  * Copyright (C) 2016 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.view.cts;
18 
19 import static org.junit.Assert.fail;
20 
21 import android.app.Activity;
22 import android.content.Context;
23 import android.content.pm.ActivityInfo;
24 import android.content.res.AssetManager;
25 import android.graphics.Bitmap;
26 import android.graphics.BitmapFactory;
27 import android.graphics.Canvas;
28 import android.graphics.Point;
29 import android.graphics.Rect;
30 import android.os.Bundle;
31 import android.view.View;
32 import android.view.ViewTreeObserver.OnDrawListener;
33 import android.view.cts.util.DisplayUtils;
34 
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.util.concurrent.CountDownLatch;
38 import java.util.concurrent.TimeUnit;
39 
40 public class PixelCopyWideGamutViewProducerActivity extends Activity implements OnDrawListener {
41     private static final int[] ORIENTATIONS = {
42             ActivityInfo.SCREEN_ORIENTATION_PORTRAIT,
43             ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,
44             ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT,
45             ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE,
46     };
47     private int mCurrentOrientation = 0;
48     private View mContent;
49     private Rect mContentBounds = new Rect();
50     private CountDownLatch mFence = new CountDownLatch(3);
51     private boolean mSupportsRotation;
52 
53     @Override
onCreate(Bundle savedInstanceState)54     protected void onCreate(Bundle savedInstanceState) {
55         super.onCreate(savedInstanceState);
56 
57         // Check if the device supports both of portrait and landscape orientation screens.
58         mSupportsRotation = DisplayUtils.supportOrientationRequest(this);
59         if (mSupportsRotation) {
60             setRequestedOrientation(ORIENTATIONS[mCurrentOrientation]);
61         }
62 
63         mContent = new WideGamutBitmapView(this);
64         setContentView(mContent);
65         View view = this.getWindow().getDecorView();
66         view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
67         mContent.getViewTreeObserver().addOnDrawListener(this);
68     }
69 
70     @Override
onDraw()71     public void onDraw() {
72         final int requestedOrientation = ORIENTATIONS[mCurrentOrientation];
73         boolean isRequestingPortrait =
74                 requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
75                 || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
76         if (mSupportsRotation && (isRequestingPortrait != DisplayUtils.isDevicePortrait(this))) {
77             return;
78         }
79         mContent.post(() -> {
80             Point offset = new Point();
81             // We pass mContentBounds here just as a throwaway rect, we don't care about
82             // the visible rect just the global offset.
83             mContent.getGlobalVisibleRect(mContentBounds, offset);
84             mContentBounds.set(offset.x, offset.y,
85                     offset.x + mContent.getWidth(), offset.y + mContent.getHeight());
86             mFence.countDown();
87             if (mFence.getCount() > 0) {
88                 mContent.invalidate();
89             }
90         });
91     }
92 
waitForFirstDrawCompleted(int timeout, TimeUnit unit)93     public void waitForFirstDrawCompleted(int timeout, TimeUnit unit) {
94         try {
95             if (!mFence.await(timeout, unit)) {
96                 fail("Timeout");
97             }
98         } catch (InterruptedException ex) {
99             fail(ex.getMessage());
100         }
101     }
102 
rotate()103     public boolean rotate() {
104         if (!mSupportsRotation) {
105             // Do not rotate the screen if it is not supported.
106             return false;
107         }
108         mFence = new CountDownLatch(3);
109         runOnUiThread(() -> {
110             mCurrentOrientation = (mCurrentOrientation + 1) % ORIENTATIONS.length;
111             setRequestedOrientation(ORIENTATIONS[mCurrentOrientation]);
112         });
113         waitForFirstDrawCompleted(3, TimeUnit.SECONDS);
114         return mCurrentOrientation != 0;
115     }
116 
offsetForContent(Rect inOut)117     void offsetForContent(Rect inOut) {
118         inOut.offset(mContentBounds.left, mContentBounds.top);
119     }
120 
121     private static final class WideGamutBitmapView extends View {
122         private final Bitmap mBitmap;
123 
WideGamutBitmapView(Context context)124         WideGamutBitmapView(Context context) {
125             super(context);
126             // We use an asset to ensure aapt will not mess with the data
127             AssetManager assets = context.getResources().getAssets();
128             try (InputStream in = assets.open("prophoto.png")) {
129                 mBitmap = BitmapFactory.decodeStream(in);
130             } catch (IOException e) {
131                 throw new RuntimeException("Test failed: ", e);
132             }
133         }
134 
135         @Override
onDraw(Canvas canvas)136         protected void onDraw(Canvas canvas) {
137             canvas.drawBitmap(mBitmap, 0.0f, 0.0f, null);
138         }
139     }
140 }
141