From f3a51d652ff9fbcb5a41c71c801de71a3b1ece78 Mon Sep 17 00:00:00 2001 From: John Reck Date: Wed, 27 Apr 2016 15:23:51 -0700 Subject: [PATCH] Video source test & bugfix Bug: 28428970 Test for video sources and fix a bug where we should throw an IAE for surfaces that are invalid at request time. Change-Id: I891a2b1568f583300433c7aca6de36d2e2621c63 --- graphics/java/android/view/PixelCopy.java | 3 + tests/HwAccelerationTest/AndroidManifest.xml | 9 ++ .../res/raw/colorgrid_video.mp4 | Bin 0 -> 25216 bytes .../test/hwui/VideoViewCaptureActivity.java | 89 ++++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 tests/HwAccelerationTest/res/raw/colorgrid_video.mp4 create mode 100644 tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java diff --git a/graphics/java/android/view/PixelCopy.java b/graphics/java/android/view/PixelCopy.java index 95c930c5264d3..29bf963842da4 100644 --- a/graphics/java/android/view/PixelCopy.java +++ b/graphics/java/android/view/PixelCopy.java @@ -123,6 +123,9 @@ public final class PixelCopy { public static void request(@NonNull Surface source, @NonNull Bitmap dest, @NonNull OnPixelCopyFinishedListener listener, @NonNull Handler listenerThread) { validateBitmapDest(dest); + if (!source.isValid()) { + throw new IllegalArgumentException("Surface isn't valid, source.isValid() == false"); + } // TODO: Make this actually async and fast and cool and stuff int result = ThreadedRenderer.copySurfaceInto(source, dest); listenerThread.post(new Runnable() { diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index b9e9ac8561854..3785cdc44b0c8 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -382,6 +382,15 @@ + + + + + + + diff --git a/tests/HwAccelerationTest/res/raw/colorgrid_video.mp4 b/tests/HwAccelerationTest/res/raw/colorgrid_video.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..1be8bee39fd46b94482acb4c3e38dea1b16a9164 GIT binary patch literal 25216 zcmeI*dvp_Z-pBD@Z(MpW&^EnL23mTdx1=q#fDx*T6ct%fz*V$PlWCi$Ns}fiv}ISh zw2CV#yUzj&+Ag>*ASk#BJS-IOSy#c!DmR4{5#$aEx~y10+kH>d+O*r_S^x65XL5Ko zlg#`klh5}zlbOlnAcT-g-L(#j%Wf0GSE%>Mk!P9=Hb=_?aIq#QKTpb(Om?Rt8S-)@XHIUxC~4Hld{cqBfDuJm zOprb4=i?`2=1GOqZemKaVq(Nic1NvMDRoOZdVOwYj^3corrhmzjLy!UHEUMZOp95u zTjk0uyR$4?eU+?ox6R5lc8A+yuXK%;Omc~AG8!bOQfkbV%u0#XZmKXEM(aoGCAm_z z*18m1o6t$!4ih%*E;)4YVkB z%9Uk`(U32h%AIzbTuf7gG#E{LVltvIbR6Y+eBwc07y7MtughwSFDiHzJ%*;2_Yn9wP!)08@8o8ls^ zl43_K!xpnKhhf<)JJh#PQe0w@UFwTioJ#u}o26LF%H1W5vpbZ^;xfB~v7RR#G_6o- znYS@#q`qUY*k-BZq2w|tm5Qm_ZOqfFi|LfrOr46WoaRnb@po@m9q%+5P0muuRzk4q z+v0&SCpSwkRjF^rsL#r0(4o$_{a&sy=8xhDms@cd^CXLdD$ye-BCjh~(E-$QiaB)Q zy~=`mF{Z8c_}Z31d)BXbZ`L2~xNiMFO_Nuej&9m2`BY>V&8Hdii)A2IRC2ZQXV%Z`nyu{LZPTNP42_72lTY4>1Z|Jh?tCkK7H_}tRA1D8LH ziM5}7^Q)G|){WUI5gX2C9Qmw5AAj~h(j!wIzrSYW2YX$cH#JNi==<4)@r!=D{@A&S zgZk2z{Uv8~{Y$T%Tv)VgntjjwEsN{6A6VIX*Ou+?KJ)8;x>DyIxcbNWJ6?QtQQhp8 z75mPoeST`EbmFDM$x@#ZL)hVcb9q-mh0BtxH|=O$v&82Wbv-R?ys@UC&F5Bi*r!o; z-?+o4*)weVpN`>(!e!+XR~ME)eOtd-ZJiAR3mYFEACZy$UDM~iny&I{x{jvSo=x8x zAL-TftXI?XUQNH~rD;>BchjcKuBJ`dT}_wg_11Jsx29EIOeduiI3;N7&**wwUgY**7|Nxe0_v0KyctLwiN=izQmwYnBA z*Xr7>OK9tB;c{(#_3jedc9;)IZ9CkpOK6|3p8Y26^R;syu}Rx+DqN=R4|m&2X#2y3 z%YJglIa@l8IHtF?7L3a}%JJeS%7S^qe{AciomZAj4VnJXw-#f1%e%u)CTx9hK;lax zs`>Kn-#TWv_shE%R^J|fXN)oeMmw($Z{+0pTU#UnvaAMvw zBmHMgu80YK`L(R%?1qRVb>@&5%hhEk?C+kOU|b#bPWre*&$pHhc%ypmwXFj)3s+^z z{tw+2d1%w|X|2D?fAsX_^au7Y?ANku$_u&8iFcddl>b`4|J`$A;-=mjH#_C4erGtnfCtL zKsz(7b_wkp2d}M!_KkzuCA4pnyt>4H={JPE9y!;G@V5WfBj<72k#pBK-P)0J$F&67 zIdScrxYrd7+BtFUoVa%6-2Lh*?b;vh$hpS_ciNG&cI4cnOK3;V+L3dQF7d;Tob7F` ztLptqI7$mF{DIfjdYYO%O@G+6wZ(0%3pWJ+pQq`6_DxdvBj;m67{0OD?K7E$)i$%- z%)Qsm?~D-Ddf_9~e_gk34|uxA<8fV6_BQ0plRAst>{3UD&zUo)ubAA{*4Em_vV?P$ zdIe9s$Y+G&+M!`YWy?h-4*OI>bPXQ9+-9#MZV!o7O) zo~P#-GjF?yL6v&@_bEKjcm371Q3_#Tt~dFZMPS=8p)2El-JuC%8*9c1;V1YLJpc7a zl{r45Px<-dZx7o^1D(s=o-2dui}+sf+>3Y?x4qUp_Um}=8k2k_M6|>7T^rxeI>xE} zLtV *=q0{=7O)8?WV~^$*W_(7C>7>xZ^|=-f7H+edBt_+xG#)ooJecIn4l4sAWq z)&s5oY5NK4cA#^6r0pkZ`$^hmOSG(Dp-r z%>7XHvs^tFuYS{{-n{pL7!G=eadnRN?RD1kgCR!d^fB31d z564-bwe?)<$3OLctSx`nXLWC%OWJxaL~prh{pS1ojh4?(DxaWTF1N|fXF9j`>u|Vc z%5MvHVLy(7>uvnm@Av0(-#-p1xE{A)8cHw=4fqY7#hON&me#f^#5~ zzz}fFS>SMxNnjD~!UG_a!1;I*%RwfA+wm4Y0GR|{;nE7Gx3<3>}g{ zCLt4WCyGHPA@lGAmVrz{nz0)PKqetA?56o69Apxji?O&BWD;75Iy?+A30;GYcnxF{ zdIDeI8+LigBy0%MaUIAc>>iZD2{H*=j1_nhWD@p14&w~SBs>VwNCcUL-;61^A7m0f z7mwp8Lo1rVjocRK`9uCLQFyl9QY-u z`JiX97MnrM2OY#I`~%cHav+8x6VyENcFaIIsCne0Sc>OB%_CpOUK{~6k8BenDg-g0 z=24?jgu6h^qpC3DFaXp%noOeeFb>o_noOeYm znZ!)MouKA1WD+wEPk@@okV#B4cH;oZB&J1(SbtFSSTc#t#aP@5GKsB39Ucam#IC_c zyaqCfJ%KOqjSz8U5;p|txDI3zcMnS81ewGw#tOU$GKqU1hj9jE5+8(UB!W!hZ^jhd z4>F0Li^uUa$RvInc40rrB>rn52KyllWHLAhH{ceK$zU65(Eu_Tyc(}!C&*;*aa_bT zAriC#k1r$_)OcH*F-(wxfB;h@Lgwr6CA%Td(Fp$ZR@wfx`flP+X!9qL* zG8wWJZ(<+FWXNS9BwvJrOe6!0mSVaIGx^TcQH0ycq~ zCw_>N_!87SX#gZ-fSM;w!o4U1HBVZAC0Ge+p7a;&!N;KHNv%Q*4~7oZeE29#z@4Dx z!`+yNCqT`IuSYX>gPIRNhZZ4{{Xxx>ha(qbLCurNB)JlGpytVBlDq~RLCurNB>4os z05wk`lawJy2Q^P2lazZ<3TmE0CMk=t0@OT(Oj6#*VNmlFGD!_WG^lwhnWWx~DWK-5 zWRf};kAs@0l1b_|>;g4UC6m;zg-G)QHBTdxv>e<3YMw?WX*SfN0c4W48n0p}$RzDJ zF5;RHBgkY#0!APoWHRCxP*4Rj8Sy*(9_v6RBi_SDI1MsM4@4A(flSiJ;||;hGD)9< zg?I{NlD-vhVjsvP{jv}lz6b@GWEfz?M36~_6*Z^_nPjZOE7$=t$@ml(a8-!RFbqZ- zMuJQ-?}ix;kV)qMq6uq3CYgW3-*F0LlGPuP7z#4U`Wb$X86cCahwvDdf=sghj5n|s zWRmrj5ZOKm0hwg$aXpGaCfOC3h4~

_6g9*bXwuK8DY6g`WhFi9Q~w$OD<^r^5uh z5aNMqvs>o=Zky76&!8CU{hI@Rr{I(w4l?YzrCU5dY)D+=wyQIVPx# literal 0 HcmV?d00001 diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java new file mode 100644 index 0000000000000..b87be8058d811 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.hwui; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.view.PixelCopy; +import android.view.View; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.Toast; +import android.widget.VideoView; + +import java.io.FileOutputStream; + +public class VideoViewCaptureActivity extends Activity { + private VideoView mVideoView; + private int mVideoWidth, mVideoHeight; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mVideoView = new VideoView(this); + mVideoView.setOnPreparedListener(mp -> { + mp.setLooping(true); + mVideoWidth = mp.getVideoWidth(); + mVideoHeight = mp.getVideoHeight(); + mVideoView.start(); + }); + + Uri uri = Uri.parse("android.resource://com.android.test.hwui/" + R.raw.colorgrid_video); + mVideoView.setVideoURI(uri); + + Button button = new Button(this); + button.setText("Copy bitmap to /sdcard/surfaceview.png"); + button.setOnClickListener((View v) -> { + final Bitmap b = Bitmap.createBitmap( + mVideoWidth, mVideoHeight, + Bitmap.Config.ARGB_8888); + PixelCopy.request(mVideoView, b, + (int result) -> { + if (result != PixelCopy.SUCCESS) { + Toast.makeText(VideoViewCaptureActivity.this, + "Failed to copy", Toast.LENGTH_SHORT).show(); + return; + } + try { + try (FileOutputStream out = new FileOutputStream( + Environment.getExternalStorageDirectory() + "/surfaceview.png");) { + b.compress(Bitmap.CompressFormat.PNG, 100, out); + } + } catch (Exception e) { + // Ignore + } + }, mVideoView.getHandler()); + }); + + FrameLayout content = new FrameLayout(this); + LinearLayout layout = new LinearLayout(this); + layout.setOrientation(LinearLayout.VERTICAL); + layout.addView(button, LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + layout.addView(mVideoView, LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT); + + content.addView(layout, new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT)); + setContentView(content); + } +}