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