• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // AngleNativeTest:
6 //   Helper to run Angle tests inside NativeActivity.
7 
8 package com.android.angle.test;
9 
10 import android.app.Activity;
11 import android.content.Context;
12 import android.content.Intent;
13 import android.os.Build;
14 import android.os.Bundle;
15 import android.os.Environment;
16 import android.os.Handler;
17 import android.os.Process;
18 import android.system.Os;
19 import android.util.Log;
20 import android.view.View;
21 
22 import org.chromium.build.gtest_apk.NativeTestIntent;
23 
24 import java.io.File;
25 
26 public class AngleNativeTest
27 {
28     private static final String TAG = "NativeTest";
29 
30     private String mCommandLineFilePath;
31     private StringBuilder mCommandLineFlags = new StringBuilder();
32     private TestStatusReporter mReporter;
33     private String mStdoutFilePath;
34 
35     private static class ReportingUncaughtExceptionHandler
36             implements Thread.UncaughtExceptionHandler
37     {
38 
39         private TestStatusReporter mReporter;
40         private Thread.UncaughtExceptionHandler mWrappedHandler;
41 
ReportingUncaughtExceptionHandler( TestStatusReporter reporter, Thread.UncaughtExceptionHandler wrappedHandler)42         public ReportingUncaughtExceptionHandler(
43                 TestStatusReporter reporter, Thread.UncaughtExceptionHandler wrappedHandler)
44         {
45             mReporter       = reporter;
46             mWrappedHandler = wrappedHandler;
47         }
48 
49         @Override
uncaughtException(Thread thread, Throwable ex)50         public void uncaughtException(Thread thread, Throwable ex)
51         {
52             mReporter.uncaughtException(Process.myPid(), ex);
53             if (mWrappedHandler != null) mWrappedHandler.uncaughtException(thread, ex);
54         }
55     }
56 
postCreate(Activity activity)57     public void postCreate(Activity activity)
58     {
59         parseArgumentsFromIntent(activity, activity.getIntent());
60         mReporter = new TestStatusReporter(activity);
61         mReporter.testRunStarted(Process.myPid());
62         Thread.setDefaultUncaughtExceptionHandler(new ReportingUncaughtExceptionHandler(
63                 mReporter, Thread.getDefaultUncaughtExceptionHandler()));
64 
65         // Enable fullscreen mode
66         // https://developer.android.com/training/system-ui/immersive#java
67         View decorView = activity.getWindow().getDecorView();
68         if (decorView != null)
69         {
70             decorView.setSystemUiVisibility(
71                     View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN);
72         }
73     }
74 
parseArgumentsFromIntent(Activity activity, Intent intent)75     private void parseArgumentsFromIntent(Activity activity, Intent intent)
76     {
77         Log.i(TAG, "Extras:");
78         Bundle extras = intent.getExtras();
79         if (extras != null)
80         {
81             for (String s : extras.keySet())
82             {
83                 Log.i(TAG, "  " + s);
84             }
85         }
86 
87         mCommandLineFilePath = intent.getStringExtra(NativeTestIntent.EXTRA_COMMAND_LINE_FILE);
88         if (mCommandLineFilePath == null)
89         {
90             mCommandLineFilePath = "";
91         }
92         else
93         {
94             File commandLineFile = new File(mCommandLineFilePath);
95             if (!commandLineFile.isAbsolute())
96             {
97                 mCommandLineFilePath =
98                         Environment.getExternalStorageDirectory() + "/" + mCommandLineFilePath;
99             }
100             Log.i(TAG, "command line file path: " + mCommandLineFilePath);
101         }
102 
103         String commandLineFlags = intent.getStringExtra(NativeTestIntent.EXTRA_COMMAND_LINE_FLAGS);
104         if (commandLineFlags != null) mCommandLineFlags.append(commandLineFlags);
105 
106         String gtestFilter = intent.getStringExtra(NativeTestIntent.EXTRA_GTEST_FILTER);
107         if (gtestFilter != null)
108         {
109             appendCommandLineFlags("--gtest_filter=" + gtestFilter);
110         }
111 
112         mStdoutFilePath = intent.getStringExtra(NativeTestIntent.EXTRA_STDOUT_FILE);
113     }
114 
appendCommandLineFlags(String flags)115     private void appendCommandLineFlags(String flags)
116     {
117         mCommandLineFlags.append(" ").append(flags);
118     }
119 
postStart(final Activity activity)120     public void postStart(final Activity activity)
121     {
122         final Runnable runTestsTask = new Runnable() {
123             @Override
124             public void run()
125             {
126                 runTests(activity);
127             }
128         };
129 
130         // Post a task that posts a task that creates a new thread and runs tests on it.
131         // This is needed because NativeActivity processes Looper messages in native code code,
132         // which makes invoking the test runner Handler problematic.
133 
134         // On L and M, the system posts a task to the main thread that prints to stdout
135         // from android::Layout (https://goo.gl/vZA38p). Chaining the subthread creation
136         // through multiple tasks executed on the main thread ensures that this task
137         // runs before we start running tests s.t. its output doesn't interfere with
138         // the test output. See crbug.com/678146 for additional context.
139 
140         final Handler handler              = new Handler();
141         final Runnable startTestThreadTask = new Runnable() {
142             @Override
143             public void run()
144             {
145                 new Thread(runTestsTask).start();
146             }
147         };
148         final Runnable postTestStarterTask = new Runnable() {
149             @Override
150             public void run()
151             {
152                 handler.post(startTestThreadTask);
153             }
154         };
155         handler.post(postTestStarterTask);
156     }
157 
runTests(Activity activity)158     private void runTests(Activity activity)
159     {
160         Log.i(TAG, "runTests: " + mCommandLineFlags.toString());
161         nativeRunTests(mCommandLineFlags.toString(), mCommandLineFilePath, mStdoutFilePath);
162         Log.i(TAG, "runTests finished");
163         activity.finish();
164         mReporter.testRunFinished(Process.myPid());
165     }
166 
167     // Signal a failure of the native test loader to python scripts
168     // which run tests.  For example, we look for
169     // RUNNER_FAILED build/android/test_package.py.
nativeTestFailed()170     private void nativeTestFailed()
171     {
172         Log.e(TAG, "[ RUNNER_FAILED ] could not load native library");
173     }
174 
nativeRunTests( String commandLineFlags, String commandLineFilePath, String stdoutFilePath)175     private native void nativeRunTests(
176             String commandLineFlags, String commandLineFilePath, String stdoutFilePath);
177 }
178