1 /*
2  * Copyright 2019 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 
7 package org.chromium.c2.test;
8 
9 import android.app.Activity;
10 import android.content.BroadcastReceiver;
11 import android.content.Context;
12 import android.content.Intent;
13 import android.content.IntentFilter;
14 import android.os.AsyncTask;
15 import android.os.Bundle;
16 import android.os.Handler;
17 import android.os.Looper;
18 import android.util.Log;
19 import android.util.Size;
20 import android.view.Surface;
21 import android.view.SurfaceHolder;
22 import android.view.SurfaceView;
23 import android.widget.LinearLayout;
24 
25 import java.util.concurrent.CountDownLatch;
26 
27 /** Activity responsible for running the native Codec2.0 E2E tests. */
28 public class E2eTestActivity extends Activity implements SurfaceHolder.Callback {
29 
30     public final String TAG = "E2eTestActivity";
31 
32     private SurfaceView mSurfaceView;
33     private Size mSize;
34 
35     private boolean mSurfaceCreated = false;
36     private boolean mCanStartTest = false;
37     private Size mExpectedSize;
38     private CountDownLatch mLatch;
39 
40     private long mCodecPtr = 0;
41 
42     private BroadcastReceiver mCodecConfigReceiver;
43 
44     @Override
onCreate(Bundle savedInstanceState)45     protected void onCreate(Bundle savedInstanceState) {
46         super.onCreate(savedInstanceState);
47 
48         System.loadLibrary("codectest");
49 
50         setContentView(R.layout.main_activity);
51         mSurfaceView = (SurfaceView) findViewById(R.id.surface);
52 
53         mSurfaceView.getHolder().addCallback(this);
54 
55         mCanStartTest = !getIntent().getBooleanExtra("delay-start", false);
56 
57         mCodecConfigReceiver = new CodecReadyReceiver();
58         registerReceiver(
59                 mCodecConfigReceiver,
60                 new IntentFilter("org.chromium.c2.test.CHECK_CODEC_CONFIGURED"));
61     }
62 
63     @Override
onDestroy()64     protected void onDestroy() {
65         super.onDestroy();
66         unregisterReceiver(mCodecConfigReceiver);
67         // gtest can't reuse a process
68         System.exit(0);
69     }
70 
71     @Override
surfaceCreated(SurfaceHolder holder)72     public void surfaceCreated(SurfaceHolder holder) {
73         mSurfaceCreated = true;
74         maybeStartTest();
75     }
76 
maybeStartTest()77     private void maybeStartTest() {
78         if (!mSurfaceCreated || !mCanStartTest) {
79             return;
80         }
81         boolean encode = getIntent().getBooleanExtra("do-encode", false);
82         String[] testArgs =
83                 getIntent().getStringArrayExtra("test-args") != null
84                         ? getIntent().getStringArrayExtra("test-args")
85                         : new String[0];
86         String logFile = getIntent().getStringExtra("log-file");
87 
88         AsyncTask.execute(
89                 new Runnable() {
90                     @Override
91                     public void run() {
92                         int res =
93                                 c2VideoTest(
94                                         encode,
95                                         testArgs,
96                                         testArgs.length,
97                                         mSurfaceView.getHolder().getSurface(),
98                                         logFile);
99                         Log.i(TAG, "Test returned result code " + res);
100 
101                         new Handler(Looper.getMainLooper())
102                                 .post(
103                                         new Runnable() {
104                                             @Override
105                                             public void run() {
106                                                 finish();
107                                             }
108                                         });
109                     }
110                 });
111     }
112 
onCodecReady(long codecPtr)113     void onCodecReady(long codecPtr) {
114         synchronized (this) {
115             mCodecPtr = codecPtr;
116         }
117     }
118 
119     @Override
onNewIntent(Intent intent)120     public void onNewIntent(Intent intent) {
121         if (intent.getAction().equals("org.chromium.c2.test.START_TEST")) {
122             mCanStartTest = true;
123             maybeStartTest();
124             return;
125         }
126 
127         synchronized (this) {
128             if (mCodecPtr != 0) {
129                 stopDecoderLoop(mCodecPtr);
130             }
131         }
132     }
133 
134     @Override
surfaceChanged(SurfaceHolder holder, int format, int width, int height)135     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
136         synchronized (this) {
137             mSize = new Size(width, height);
138             if (mLatch != null && mExpectedSize.equals(mSize)) {
139                 mLatch.countDown();
140             }
141         }
142     }
143 
144     // Configures the SurfaceView with the dimensions of the video the test is currently playing.
onSizeChanged(int width, int height)145     void onSizeChanged(int width, int height) {
146         synchronized (this) {
147             mExpectedSize = new Size(width, height);
148             if (mSize != null && mSize.equals(mExpectedSize)) {
149                 return;
150             }
151             mLatch = new CountDownLatch(1);
152         }
153 
154         new Handler(Looper.getMainLooper())
155                 .post(
156                         new Runnable() {
157                             @Override
158                             public void run() {
159                                 mSurfaceView.setLayoutParams(
160                                         new LinearLayout.LayoutParams(width, height));
161                             }
162                         });
163 
164         try {
165             mLatch.await();
166         } catch (Exception e) {
167         }
168         synchronized (this) {
169             mLatch = null;
170         }
171     }
172 
173     @Override
surfaceDestroyed(SurfaceHolder holder)174     public void surfaceDestroyed(SurfaceHolder holder) {
175         if (!isFinishing()) {
176             throw new RuntimeException("Surface destroyed during test");
177         }
178     }
179 
180     class CodecReadyReceiver extends BroadcastReceiver {
181         @Override
onReceive(Context ctx, Intent intent)182         public void onReceive(Context ctx, Intent intent) {
183             boolean ready;
184             synchronized (E2eTestActivity.this) {
185                 ready = mCodecPtr != 0;
186             }
187             setResultCode(ready ? 1 : 0);
188         }
189     }
190 
c2VideoTest( boolean encode, String[] testArgs, int testArgsCount, Surface surface, String tmpFile)191     public native int c2VideoTest(
192             boolean encode, String[] testArgs, int testArgsCount, Surface surface, String tmpFile);
193 
stopDecoderLoop(long decoderPtr)194     public native void stopDecoderLoop(long decoderPtr);
195 }
196