diff --git a/.github/workflows/testing-linux.yml b/.github/workflows/testing-linux.yml index dfb194bf855c..82ad598b0f6b 100644 --- a/.github/workflows/testing-linux.yml +++ b/.github/workflows/testing-linux.yml @@ -114,3 +114,99 @@ jobs: cmake --build build ctest --test-dir build --build-config RelWithDebInfo --output-on-failure -LE performance -j "$(nproc)" ctest --test-dir build --build-config RelWithDebInfo --output-on-failure -L performance --repeat until-pass:5 + + android-apps: + # Deliberately its own job on Ubuntu (not folded into `macos`/HelloiOS's + # job): unlike HelloiOS, cross-compiling for Android has no dependency on + # Xcode or any other macOS-only tooling, so it doesn't need to spend + # macOS CI minutes. GitHub's hosted ubuntu-24.04 image ships an Android + # SDK+NDK by default, same as its macOS image does for Xcode/HelloiOS. + # Both apps build real APKs via their own Gradle/CMake `externalNativeBuild` + # project -- Halide's generators are built as a side effect of that same + # CMake configure (see app/src/main/cpp/CMakeLists.txt in each app), so no + # separate generator pre-build step is needed here. + if: "!contains(github.event.pull_request.labels.*.name, 'skip_buildbots')" + name: HelloAndroid apps + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v7 + + - uses: astral-sh/setup-uv@v7 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libpng-dev libjpeg-dev + + - name: Sync CI environment + run: | + uv sync --group ci-llvm-main --no-install-project + echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH" + echo "VIRTUAL_ENV=${GITHUB_WORKSPACE}/.venv" >> "$GITHUB_ENV" + + - name: Configure LLVM + run: echo "Halide_LLVM_ROOT=$(halide-llvm --prefix)" >> "$GITHUB_ENV" + + - name: Configure CMake + run: >- + cmake --preset ci-linux-x86-64 + -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/install" + + - name: Build and install Halide + run: cmake --build build --target install + + - uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: "21" + + - uses: gradle/actions/setup-gradle@v4 + + - name: Point Gradle at a CMake >= 3.28 + # AGP's own bundled/SDK-managed CMake package defaults to an older + # version than Halide's CMake floor; point it at the system CMake + # (already >= 3.28, since building Halide itself above requires it) + # via the documented `cmake.dir` local.properties key instead. + run: | + cmake_dir="$(dirname "$(dirname "$(command -v cmake)")")" + echo "cmake.dir=${cmake_dir}" | tee apps/HelloAndroid/local.properties apps/HelloAndroidCamera2/local.properties + + - name: Build HelloAndroid + working-directory: apps/HelloAndroid + run: ./gradlew assembleDebug "-PHalide_ROOT=${{ github.workspace }}/install" + + - name: Build HelloAndroidCamera2 + working-directory: apps/HelloAndroidCamera2 + run: ./gradlew assembleDebug "-PHalide_ROOT=${{ github.workspace }}/install" + + - name: Enable KVM group perms (required by the emulator) + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + # Both apps' bugs found in the prior two commits (missing runtime + # permission request, native buffer bugs) were invisible to a build-only + # check -- they only showed up when the app actually ran and tried to + # open the camera. x86_64 (not arm64-v8a) so the emulator gets KVM + # hardware acceleration on these x86_64 runners. + - name: Run smoke tests on an emulator + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 34 + target: default + arch: x86_64 + profile: pixel_6 + emulator-options: >- + -no-window -gpu swiftshader_indirect -no-snapshot -noaudio + -no-boot-anim -camera-back emulated -camera-front emulated + disable-animations: true + script: | + apps/support/android_smoke_test.sh \ + apps/HelloAndroid/app/build/outputs/apk/debug/app-debug.apk \ + com.example.hellohalide .CameraActivity android.permission.CAMERA \ + "requires a buffer of exactly" + apps/support/android_smoke_test.sh \ + apps/HelloAndroidCamera2/app/build/outputs/apk/debug/app-debug.apk \ + com.example.helloandroidcamera2 .CameraActivity android.permission.CAMERA diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 5365d7b1110a..3d71d13e1927 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -55,8 +55,8 @@ add_app(fft) add_app(gaussian_blur) add_app(hannk) add_app(harris) -# add_app(HelloAndroid) # TODO(#5374): missing CMake build -# add_app(HelloAndroidCamera2) # TODO(#5374): missing CMake build +# add_app(HelloAndroid) # don't build HelloAndroid here because it is driven by gradle +# add_app(HelloAndroidCamera2) # don't build HelloAndroidCamera2 here because it is driven by gradle add_app(HelloBaremetal) # add_app(HelloiOS) # don't build HelloiOS here because it isn't universal. add_app(HelloPyTorch) diff --git a/apps/HelloAndroid/.gitignore b/apps/HelloAndroid/.gitignore index aa111da4d7fd..37f0abfb0741 100644 --- a/apps/HelloAndroid/.gitignore +++ b/apps/HelloAndroid/.gitignore @@ -1,8 +1,8 @@ -.gradle/** -gen/** -gradle_build/** -HelloAndroid.iml +.gradle/ +build/ +app/build/ +app/.cxx/ +app/.cxx-generators/ local.properties -obj/** -proguard-project.txt -project.properties +.idea/ +*.iml diff --git a/apps/HelloAndroid/README.md b/apps/HelloAndroid/README.md index dbc0b6f6e9a8..c6841dbac14a 100644 --- a/apps/HelloAndroid/README.md +++ b/apps/HelloAndroid/README.md @@ -1,75 +1,34 @@ HelloHalide is a simple application which applies a tone curve and sharpening to a video preview from the camera on a phone or tablet. -This application builds for multiple native ABIs. (At present armeabi, -armeabi-v7a, arm64-v8a, x86_64, and x86 are supported.) Halide code is generated -for each architecture. - -This build is meant to use Android command line tools. (An IDE is not required.) -In order to build, the following will be required: - -- Android NDK -- This can be downloaded here: - https://developer.android.com/tools/sdk/ndk/index.html After installing, make - sure the top-level directory of the install is in the PATH. (It should contain - an executable ndk-build file.) - -- Android SDK -- This can be downloaded here: - http://developer.android.com/sdk/index.html The standalone SDK is desired. - Once downloaded, the "android" program in the tools directory of the install - will need to be run. It should bring up a UI allowing one to choose components - to install. HelloAndroid currently depends on the android-17 release. (It can - easily be made to run on others, but that is what the scripts are setup to - build against.) Make sure the tools directory is on one's PATH. - -- Apache Ant -- which can be downloaded here: - http://ant.apache.org/bindownload.cgi make sure the bin directory is on one's - PATH. - -If everything is setup correctly, running the build.sh script in this directory, -with the current directory set to here, would build the HelloAndroid apk and -install it on a connected Android device. - -# Gradle - -To use Gradle create local.properties file in this folder with sdk.dir and -ndk.dir variables defined like so: +This app targets `arm64-v8a` and `x86_64`. The Halide pipeline +(`app/src/main/cpp/generators/hello_generator.cpp`) is compiled once per ABI via +Gradle's `externalNativeBuild`, which drives a single CMake project +(`app/src/main/cpp/CMakeLists.txt`); the Halide generator itself is built with +the host compiler as a side effect of that same CMake configure, so no separate +pre-build step is needed. + +## Prerequisites + +- A local Halide install (built via CMake -- see the top-level + `doc/BuildingHalideWithCMake.md`). +- Android Studio, or the Android SDK + NDK (Android Studio's SDK Manager can + install the NDK under SDK Tools -- "NDK (Side by side)"). +- A CMake >= 3.28. The CMake bundled with the Android SDK by default is often + older than this; if so, point Gradle at a newer one by adding + `cmake.dir== 3.28 install prefix>` to `local.properties` + (e.g. `cmake.dir=/opt/homebrew` for a Homebrew-installed CMake on macOS). + +## Building ``` -sdk.dir=/Users/joe/Downloads/android-sdk -ndk.dir=/Users/joe/Downloads/android-ndk +./gradlew assembleDebug -PHalide_ROOT= ``` -After that run `gradlew build` which will produce .apk file ready for deployment -to the Android device. - -On Linux/Mac you can use `build-gradle.sh` to build, deploy and run this sample -application. - -Pay attention to the list of platforms supported by your Halide installation. -They are listed in jni/Application.mk APP_ABI variable and in build.gradle archs -map. For example, if your Halide installation was built without arm64-v8a, -remove it from APP_ABI and archs. Both list and map should match, otherwise you -will be getting compilation errors complaining about a missing hello.h file: - -``` -:compileDebugNdkClassic FAILED - -FAILURE: Build failed with an exception. - -* What went wrong: -Execution failed for task ':compileDebugNdkClassic'. -... - Output: - /private/tmp/7/halide/apps/HelloAndroid/jni/native.cpp:9:30: fatal error: hello.h: No such file or directory - #include "hello.h" - -``` - -# Android Studio - -To load project into Android Studio use "File/Import Project..." in Android -Studio and point to apps/HelloAndroid/build.gradle file. +(`Halide_ROOT` can also be provided via an environment variable of the same +name.) This produces `app/build/outputs/apk/debug/app-debug.apk`, installable +with `adb install`. -You will have to edit automatically-generated local.properties file to add -ndk.dir property so it points to your Android NDK installation as described in -Gradle section above. +To build in Android Studio instead, open this directory as a project, add +`Halide_ROOT=` to `gradle.properties` (or +`local.properties`), and use the Run button. diff --git a/apps/HelloAndroid/ant.properties b/apps/HelloAndroid/ant.properties deleted file mode 100644 index 73031c7a7241..000000000000 --- a/apps/HelloAndroid/ant.properties +++ /dev/null @@ -1,16 +0,0 @@ -# This file is used to override default values used by the Ant build system. -# -# This file must be checked into Version Control Systems, as it is -# integral to the build system of your project. - -# This file is only used by the Ant script. - -# You can use this to override default values such as -# 'source.dir' for the location of your java source folder and -# 'out.dir' for the location of your output folder. - -# You can also use it define how the release builds are signed by declaring -# the following properties: -# 'key.store' for the location of your keystore and -# 'key.alias' for the name of the key to use. -# The password will be asked during the build when you use the 'release' target. diff --git a/apps/HelloAndroid/app/build.gradle b/apps/HelloAndroid/app/build.gradle new file mode 100644 index 000000000000..58199828ea4a --- /dev/null +++ b/apps/HelloAndroid/app/build.gradle @@ -0,0 +1,55 @@ +plugins { + id "com.android.application" +} + +def halideRoot = project.findProperty("Halide_ROOT") ?: System.getenv("Halide_ROOT") +if (halideRoot == null) { + throw new GradleException( + "Set -PHalide_ROOT= (or the Halide_ROOT " + + "environment variable) to point this build at a Halide installation." + ) +} + +android { + namespace = "com.example.hellohalide" + compileSdk = 37 + + defaultConfig { + applicationId = "com.example.hellohalide" + minSdk = 21 + targetSdk = 37 + versionCode = 1 + versionName = "1.0" + + ndk { + abiFilters.addAll("arm64-v8a", "x86_64") + } + + externalNativeBuild { + cmake { + arguments "-DCMAKE_PREFIX_PATH=${halideRoot}" + } + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + externalNativeBuild { + cmake { + path = "src/main/cpp/CMakeLists.txt" + } + } + + buildTypes { + release { + minifyEnabled = false + } + } +} + +dependencies { + implementation "androidx.core:core:1.13.1" +} diff --git a/apps/HelloAndroid/AndroidManifest.xml b/apps/HelloAndroid/app/src/main/AndroidManifest.xml similarity index 81% rename from apps/HelloAndroid/AndroidManifest.xml rename to apps/HelloAndroid/app/src/main/AndroidManifest.xml index 6e6819ce85dd..0c2fc82b1b94 100644 --- a/apps/HelloAndroid/AndroidManifest.xml +++ b/apps/HelloAndroid/app/src/main/AndroidManifest.xml @@ -1,11 +1,11 @@ - + + + @@ -17,8 +17,4 @@ - - - - diff --git a/apps/HelloAndroid/app/src/main/cpp/CMakeLists.txt b/apps/HelloAndroid/app/src/main/cpp/CMakeLists.txt new file mode 100644 index 000000000000..1cdb0312137e --- /dev/null +++ b/apps/HelloAndroid/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.28) +project(HelloAndroid) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED YES) +set(CMAKE_CXX_EXTENSIONS NO) + +# This file configures itself twice: once as a host build (to compile the +# generator) and once as this target build (driven by AGP's +# externalNativeBuild, under the NDK cross toolchain). See "Use +# add_halide_generator" in doc/HalideCMakePackage.md. +set(HelloAndroid-halide_generators_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../.cxx-generators") +if (ANDROID) + # NO_CMAKE_FIND_ROOT_PATH: bypass the NDK toolchain's sysroot-only search. + find_program(HelloAndroid_NATIVE_CXX REQUIRED NAMES c++ clang++ g++ NO_CMAKE_FIND_ROOT_PATH) + + execute_process( + COMMAND + ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR} -B ${HelloAndroid-halide_generators_ROOT} + -DCMAKE_CXX_COMPILER=${HelloAndroid_NATIVE_CXX} + -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} + COMMAND_ERROR_IS_FATAL ANY + ) + + execute_process( + COMMAND ${CMAKE_COMMAND} --build ${HelloAndroid-halide_generators_ROOT} + COMMAND_ERROR_IS_FATAL ANY + ) +endif () + +# Halide is a host-built config package, not part of the Android sysroot. +find_package(Halide REQUIRED CMAKE_FIND_ROOT_PATH_BOTH) + +add_halide_generator(hello_generator SOURCES generators/hello_generator.cpp) + +if (NOT ANDROID) + # We're just building the Halide generators. + return() +endif () + +add_halide_library(hello FROM HelloAndroid::halide_generators::hello_generator) + +add_library(HelloAndroid SHARED hello_wrapper.cpp) +target_link_libraries(HelloAndroid PRIVATE hello log android) diff --git a/apps/HelloAndroid/jni/hello_generator.cpp b/apps/HelloAndroid/app/src/main/cpp/generators/hello_generator.cpp similarity index 100% rename from apps/HelloAndroid/jni/hello_generator.cpp rename to apps/HelloAndroid/app/src/main/cpp/generators/hello_generator.cpp diff --git a/apps/HelloAndroid/jni/hello_wrapper.cpp b/apps/HelloAndroid/app/src/main/cpp/hello_wrapper.cpp similarity index 98% rename from apps/HelloAndroid/jni/hello_wrapper.cpp rename to apps/HelloAndroid/app/src/main/cpp/hello_wrapper.cpp index a467a60a6272..cc151667c80c 100644 --- a/apps/HelloAndroid/jni/hello_wrapper.cpp +++ b/apps/HelloAndroid/app/src/main/cpp/hello_wrapper.cpp @@ -80,6 +80,7 @@ JNIEXPORT void JNICALL Java_com_example_hellohalide_CameraPreview_processFrame( if (dst) { srcBuf.host = (uint8_t *)src; srcBuf.set_host_dirty(); + srcBuf.dimensions = 2; srcBuf.dim = srcDim; srcBuf.dim[0].min = 0; srcBuf.dim[0].extent = w; @@ -97,6 +98,7 @@ JNIEXPORT void JNICALL Java_com_example_hellohalide_CameraPreview_processFrame( } dstBuf.host = dst; + dstBuf.dimensions = 2; dstBuf.dim = dstDim; dstBuf.dim[0].min = 0; dstBuf.dim[0].extent = w; diff --git a/apps/HelloAndroid/src/com/example/hellohalide/CameraActivity.java b/apps/HelloAndroid/app/src/main/java/com/example/hellohalide/CameraActivity.java similarity index 62% rename from apps/HelloAndroid/src/com/example/hellohalide/CameraActivity.java rename to apps/HelloAndroid/app/src/main/java/com/example/hellohalide/CameraActivity.java index 8c96139ad462..e27f30de1819 100644 --- a/apps/HelloAndroid/src/com/example/hellohalide/CameraActivity.java +++ b/apps/HelloAndroid/app/src/main/java/com/example/hellohalide/CameraActivity.java @@ -1,14 +1,20 @@ package com.example.hellohalide; +import android.Manifest; import android.app.Activity; -import android.os.Bundle; +import android.content.pm.PackageManager; import android.hardware.Camera; +import android.os.Bundle; import android.util.Log; import android.widget.FrameLayout; import android.view.SurfaceView; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + public class CameraActivity extends Activity { private static final String TAG = "CameraActivity"; + private static final int REQUEST_CAMERA_PERMISSION = 1; private Camera camera; private CameraPreview preview; @@ -45,6 +51,26 @@ public void onCreate(Bundle b) { @Override public void onResume() { super.onResume(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) + == PackageManager.PERMISSION_GRANTED) { + openCamera(); + } else { + ActivityCompat.requestPermissions( + this, new String[] {Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); + } + } + + @Override + public void onRequestPermissionsResult( + int requestCode, String[] permissions, int[] grantResults) { + if (requestCode == REQUEST_CAMERA_PERMISSION + && grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + openCamera(); + } + } + + private void openCamera() { camera = getCameraInstance(); preview.setCamera(camera); } diff --git a/apps/HelloAndroid/src/com/example/hellohalide/CameraPreview.java b/apps/HelloAndroid/app/src/main/java/com/example/hellohalide/CameraPreview.java similarity index 100% rename from apps/HelloAndroid/src/com/example/hellohalide/CameraPreview.java rename to apps/HelloAndroid/app/src/main/java/com/example/hellohalide/CameraPreview.java diff --git a/apps/HelloAndroid/src/com/example/hellohalide/FrameHandler.java b/apps/HelloAndroid/app/src/main/java/com/example/hellohalide/FrameHandler.java similarity index 100% rename from apps/HelloAndroid/src/com/example/hellohalide/FrameHandler.java rename to apps/HelloAndroid/app/src/main/java/com/example/hellohalide/FrameHandler.java diff --git a/apps/HelloAndroid/res/drawable-hdpi/ic_launcher.png b/apps/HelloAndroid/app/src/main/res/drawable-hdpi/ic_launcher.png similarity index 100% rename from apps/HelloAndroid/res/drawable-hdpi/ic_launcher.png rename to apps/HelloAndroid/app/src/main/res/drawable-hdpi/ic_launcher.png diff --git a/apps/HelloAndroid/res/drawable-ldpi/ic_launcher.png b/apps/HelloAndroid/app/src/main/res/drawable-ldpi/ic_launcher.png similarity index 100% rename from apps/HelloAndroid/res/drawable-ldpi/ic_launcher.png rename to apps/HelloAndroid/app/src/main/res/drawable-ldpi/ic_launcher.png diff --git a/apps/HelloAndroid/res/drawable-mdpi/ic_launcher.png b/apps/HelloAndroid/app/src/main/res/drawable-mdpi/ic_launcher.png similarity index 100% rename from apps/HelloAndroid/res/drawable-mdpi/ic_launcher.png rename to apps/HelloAndroid/app/src/main/res/drawable-mdpi/ic_launcher.png diff --git a/apps/HelloAndroid/res/drawable-xhdpi/ic_launcher.png b/apps/HelloAndroid/app/src/main/res/drawable-xhdpi/ic_launcher.png similarity index 100% rename from apps/HelloAndroid/res/drawable-xhdpi/ic_launcher.png rename to apps/HelloAndroid/app/src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/apps/HelloAndroid/res/layout/main.xml b/apps/HelloAndroid/app/src/main/res/layout/main.xml similarity index 100% rename from apps/HelloAndroid/res/layout/main.xml rename to apps/HelloAndroid/app/src/main/res/layout/main.xml diff --git a/apps/HelloAndroid/res/values/strings.xml b/apps/HelloAndroid/app/src/main/res/values/strings.xml similarity index 100% rename from apps/HelloAndroid/res/values/strings.xml rename to apps/HelloAndroid/app/src/main/res/values/strings.xml diff --git a/apps/HelloAndroid/build-gradle.sh b/apps/HelloAndroid/build-gradle.sh deleted file mode 100755 index da713d08767f..000000000000 --- a/apps/HelloAndroid/build-gradle.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -# Gradle needs to know where the NDK is. -# The easiest way is to set the ANDROID_NDK_HOME environment variable. -# Otherwise, set ndk.dir in local.properties (even though the file itself says -# that it's only used by ant). -# However, if you run "android update" (say, via build.sh), this variable will -# be clobbered. -./gradlew build && adb install -r gradle_build/outputs/apk/HelloAndroid-debug.apk && adb shell am start com.example.hellohalide/com.example.hellohalide.CameraActivity diff --git a/apps/HelloAndroid/build.gradle b/apps/HelloAndroid/build.gradle index 55014586d546..f50bb1305913 100644 --- a/apps/HelloAndroid/build.gradle +++ b/apps/HelloAndroid/build.gradle @@ -1,167 +1,3 @@ -import org.apache.tools.ant.taskdefs.condition.Os - -// Avoid conflicts with Bazel on case-insensitive filesystems -buildDir = 'gradle_build' - -repositories { - jcenter() -} - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.2.2' - } - -} - -//////////////////////////////////////////////////////////////////////////////// -// Use gradle's native C++ plugin to build the Halide generator. -// -// sources: defines all the C++ source files. We only have one SourceSet called -// hello_generator. -// -// executables: we only make one binary called hello_generator. Here is where -// we pass compiler and linker flags. -// -// binaries.withType: binaries is a collection, which in our case is just the -// hello_generator executable. withType() filters the collection by type. -// binary is the iteration variable. -> defines the body of the lambda: -// for each binary: -// for each halide_target / Android ABI mapping: -// for each generator: -// run the generator with -g and target set -// make the later ndkBuild task depend on this task. - -apply plugin: "cpp" - -sources { - hello_generator { - cpp(CppSourceSet) { - source { - srcDirs "jni/", "${projectDir}/../../tools/" - include "hello_generator.cpp", "GenGen.cpp" - } - } - } -} - -executables { - hello_generator { - binaries.all { - cppCompiler.args "-std=c++17", "-g", "-Wall", "-fno-rtti", "-I", "${projectDir}/../../include", "-I", "${projectDir}/../../build/include" - // "/bin" assumes Makefile build for Halide; "/build/lib" assumes CMake build - linker.args "-lHalide", "-ldl", "-lpthread", "-lz", "-L", "${projectDir}/../../bin", "-L", "${projectDir}/../../build/lib" - } - } -} - -binaries.withType(NativeExecutableBinary) { binary -> - def bin = "${projectDir}/bin" - def linkTask = binary.tasks.link - println "linktask output file is " + linkTask.outputFile - Map archs = [ - // armeabi and armeabi-v7a are the same as far as Halide is concerned - "armeabi": "arm-32-android", - "armeabi-v7a": "arm-32-android", - "arm64-v8a": "arm-64-android", - "x86_64": "x86-64-android-sse41", - "x86": "x86-32-android" - ] - archs.each { - arch -> println "creating task for: " + arch.key + " -> " + arch.value - def android_abi = arch.key - def hl_target = arch.value - def task_name = "generate_halide_binary_${binary.name.capitalize()}_${android_abi}" - def destDir = new File(bin, "${android_abi}") - def generateHalideTask = task(task_name) { - dependsOn linkTask - doFirst { - println "Executing: " + linkTask.outputFile + " ..." - destDir.mkdirs() - def envVars = [ "DYLD_LIBRARY_PATH=${projectDir}/../../bin", "LD_LIBRARY_PATH=${projectDir}/../../bin" ] - def proc = [linkTask.outputFile, "-g", "hello", "-o", "${destDir}", "target=${hl_target}"].execute(envVars, destDir) - proc.waitFor() - if (proc.exitValue() != 0) { - println "return code: ${proc.exitValue()}" - println "stderr: ${proc.err.text}" - println "stdout: ${proc.in.text}" - } - } - } - - // Call this task generateHalideTask. - binary.builtBy generateHalideTask - - // Tell gradle that the task called "ndkBuild" below depends - // on generateHalideTask. - ndkBuild.dependsOn generateHalideTask - } - println "done with archs" -} - - -//////////////////////////////////////////////////////////////////////////////// - -apply plugin: 'com.android.application' - -android { - compileSdkVersion 21 - buildToolsVersion "21.1.2" - - defaultConfig { - applicationId "com.example.hellohalide" - minSdkVersion 21 - targetSdkVersion 21 - versionCode 1 - versionName "1.0" - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - - sourceSets { - main { - java.srcDirs = ["src/"] - // Setting jni.srcDirs to [] disables the automatic ndk-build call - // which would use parameters defined in build.gradle. Use our own - // task (ndkBuild) below. - jni.srcDirs = [] - jniLibs.srcDirs = ["bin/lib/"] // default is src/main/jniLibs - manifest.srcFile "AndroidManifest.xml" - res.srcDirs = ["res/"] // default is src/main/res - } - } - - // Call regular ndk-build (ndk-build.cmd on Windows) script from - // app directory. - task ndkBuild(type: Exec) { - def ndkDir = project.android.ndkDirectory - def ndkBuildCmd = "" - if (Os.isFamily(Os.FAMILY_WINDOWS)) { - ndkBuildCmd = "ndk-build.cmd" - } else { - ndkBuildCmd = "ndk-build" - } - commandLine "$ndkDir/$ndkBuildCmd", "NDK_GEN_OUT=./bin/gen", "NDK_LIBS_OUT=./bin/lib", "NDK_OUT=./bin/obj" - } - - tasks.withType(JavaCompile) { - compileTask -> compileTask.dependsOn ndkBuild - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -task wrapper(type: Wrapper) { - gradleVersion = '2.2' +plugins { + id "com.android.application" version "9.3.0" apply false } diff --git a/apps/HelloAndroid/build.sh b/apps/HelloAndroid/build.sh deleted file mode 100755 index 7c9b784cede8..000000000000 --- a/apps/HelloAndroid/build.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -set -e -android update project -p . --target android-17 -mkdir -p bin -c++ jni/hello_generator.cpp ../../tools/GenGen.cpp \ - -g -fno-rtti -Wall -std=c++17 \ - -I ../../include -I ../../build/include \ - -L ../../bin -lHalide -ldl -lpthread -lz \ - -o bin/hello_generator - -for archs in arm-32-android,armeabi arm-32-android-armv7s,armeabi-v7a arm-64-android,arm64-v8a x86-64-android-sse41,x86_64 x86-32-android,x86; do - IFS=, - set $archs - HL_TARGET=$1 - ANDROID_ABI=$2 - mkdir -p bin/"$ANDROID_ABI" - ./bin/hello_generator -g hello -o bin/"$ANDROID_ABI" target="$HL_TARGET" - unset IFS -done - -pwd -ndk-build NDK_GEN_OUT=./bin/gen NDK_LIBS_OUT=./bin/lib NDK_OUT=./bin/obj -ant debug -adb install -r bin/HelloAndroid-debug.apk -adb logcat diff --git a/apps/HelloAndroid/build.xml b/apps/HelloAndroid/build.xml deleted file mode 100644 index 52a06f184570..000000000000 --- a/apps/HelloAndroid/build.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/HelloAndroid/gradle.properties b/apps/HelloAndroid/gradle.properties new file mode 100644 index 000000000000..08df1c9e689b --- /dev/null +++ b/apps/HelloAndroid/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx2048m +android.useAndroidX=true diff --git a/apps/HelloAndroid/gradle/wrapper/gradle-wrapper.jar b/apps/HelloAndroid/gradle/wrapper/gradle-wrapper.jar index c97a8bdb9088..b1b8ef56b44f 100644 Binary files a/apps/HelloAndroid/gradle/wrapper/gradle-wrapper.jar and b/apps/HelloAndroid/gradle/wrapper/gradle-wrapper.jar differ diff --git a/apps/HelloAndroid/gradle/wrapper/gradle-wrapper.properties b/apps/HelloAndroid/gradle/wrapper/gradle-wrapper.properties index e2fa5f40d5de..a9db11550c62 100644 --- a/apps/HelloAndroid/gradle/wrapper/gradle-wrapper.properties +++ b/apps/HelloAndroid/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,9 @@ -#Mon Jan 05 14:23:44 PST 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip +networkTimeout=10000 +retries=0 +retryBackOffMs=500 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-bin.zip diff --git a/apps/HelloAndroid/gradlew b/apps/HelloAndroid/gradlew index b7f5eb101083..249efbb032ce 100755 --- a/apps/HelloAndroid/gradlew +++ b/apps/HelloAndroid/gradlew @@ -1,70 +1,128 @@ -#!/usr/bin/env bash +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# 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 +# +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# gradlew start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh gradlew +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum -warn ( ) { +warn () { echo "$*" -} +} >&2 -die ( ) { +die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false +msys=false darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -73,84 +131,118 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/apps/HelloAndroid/gradlew.bat b/apps/HelloAndroid/gradlew.bat index aec99730b4e8..8508ef684d4e 100644 --- a/apps/HelloAndroid/gradlew.bat +++ b/apps/HelloAndroid/gradlew.bat @@ -1,90 +1,82 @@ -@if "%DEBUG%" == "" @echo off +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants +if exist "%JAVA_EXE%" goto execute -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 -:mainEnd -if "%OS%"=="Windows_NT" endlocal +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/apps/HelloAndroid/jni/Android.mk b/apps/HelloAndroid/jni/Android.mk deleted file mode 100644 index b358ced0a03a..000000000000 --- a/apps/HelloAndroid/jni/Android.mk +++ /dev/null @@ -1,15 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := HelloAndroid -LOCAL_ARM_MODE := arm -LOCAL_SRC_FILES := hello_wrapper.cpp -LOCAL_LDFLAGS := -L$(LOCAL_PATH)/../jni -LOCAL_LDLIBS := -lm -llog -landroid $(LOCAL_PATH)/../bin/$(TARGET_ARCH_ABI)/hello.a -LOCAL_STATIC_LIBRARIES := android_native_app_glue -LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../../build/include $(LOCAL_PATH)/../bin/$(TARGET_ARCH_ABI)/ - -include $(BUILD_SHARED_LIBRARY) - -$(call import-module,android/native_app_glue) diff --git a/apps/HelloAndroid/jni/Application.mk b/apps/HelloAndroid/jni/Application.mk deleted file mode 100644 index 0952046c5c83..000000000000 --- a/apps/HelloAndroid/jni/Application.mk +++ /dev/null @@ -1,4 +0,0 @@ -APP_ABI := armeabi armeabi-v7a arm64-v8a x86_64 x86 -APP_PLATFORM := android-17 -APP_STL := gnustl_static -APP_CPPFLAGS := -std=c++17 diff --git a/apps/HelloAndroid/settings.gradle b/apps/HelloAndroid/settings.gradle new file mode 100644 index 000000000000..246fc74fdfbd --- /dev/null +++ b/apps/HelloAndroid/settings.gradle @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "HelloAndroid" +include(":app") diff --git a/apps/HelloAndroidCamera2/.gitignore b/apps/HelloAndroidCamera2/.gitignore index 52d5183ab009..37f0abfb0741 100644 --- a/apps/HelloAndroidCamera2/.gitignore +++ b/apps/HelloAndroidCamera2/.gitignore @@ -1,8 +1,8 @@ -.gradle/** -gen/** -gradle_build/** -*.iml +.gradle/ +build/ +app/build/ +app/.cxx/ +app/.cxx-generators/ local.properties -obj/** -proguard-project.txt -project.properties +.idea/ +*.iml diff --git a/apps/HelloAndroidCamera2/README.md b/apps/HelloAndroidCamera2/README.md index 629417e08cf8..748a4f31843e 100644 --- a/apps/HelloAndroidCamera2/README.md +++ b/apps/HelloAndroidCamera2/README.md @@ -20,75 +20,35 @@ a logcat error message that looks something like: E/halide_native( 6146): ANativeWindow buffer locked but its size was 1920 x 1440, expected 1440 x 1080 -This application builds for multiple native ABIs. (At present armeabi, -armeabi-v7a, arm64-v8a, x86_64, and x86 are supported.) Halide code is generated -for each architecture. - -This build is meant to use Android command line tools. (An IDE is not required.) -In order to build, the following will be required: - -- Android NDK -- This can be downloaded here: - https://developer.android.com/tools/sdk/ndk/index.html After installing, make - sure the top-level directory of the install is in the PATH. (It should contain - an executable ndk-build file.) - -- Android SDK -- This can be downloaded here: - http://developer.android.com/sdk/index.html The standalone SDK is desired. - Once downloaded, the "android" program in the tools directory of the install - will need to be run. It should bring up a UI allowing one to choose components - to install. HelloAndroidCamera2 currently depends on the android-21 release. - Make sure the tools directory is on one's PATH. - -- Apache Ant -- which can be downloaded here: - http://ant.apache.org/bindownload.cgi make sure the bin directory is on one's - PATH. - -If everything is setup correctly, running the build.sh script in this directory, -with the current directory set to here, would build the HelloAndroidCamera2 apk -and install it on a connected Android device. - -# Gradle - -To use Gradle create local.properties file in this folder with sdk.dir and -ndk.dir variables defined like so: +This app targets `arm64-v8a` and `x86_64`. The two Halide pipelines +(`app/src/main/cpp/generators/deinterleave_generator.cpp`, +`edge_detect_generator.cpp`) are compiled once per ABI via Gradle's +`externalNativeBuild`, which drives a single CMake project +(`app/src/main/cpp/CMakeLists.txt`); the Halide generators themselves are built +with the host compiler as a side effect of that same CMake configure, so no +separate pre-build step is needed. + +## Prerequisites + +- A local Halide install (built via CMake -- see the top-level + `doc/BuildingHalideWithCMake.md`). +- Android Studio, or the Android SDK + NDK (Android Studio's SDK Manager can + install the NDK under SDK Tools -- "NDK (Side by side)"). +- A CMake >= 3.28. The CMake bundled with the Android SDK by default is often + older than this; if so, point Gradle at a newer one by adding + `cmake.dir== 3.28 install prefix>` to `local.properties` + (e.g. `cmake.dir=/opt/homebrew` for a Homebrew-installed CMake on macOS). + +## Building ``` -sdk.dir=/Users/joe/Downloads/android-sdk -ndk.dir=/Users/joe/Downloads/android-ndk +./gradlew assembleDebug -PHalide_ROOT= ``` -After that run `gradlew build` which will produce .apk file ready for deployment -to the Android device. - -On Linux/Mac you can use `build-gradle.sh` to build, deploy and run this sample -application. - -Pay attention to the list of platforms supported by your Halide installation. -They are listed in jni/Application.mk APP_ABI variable and in build.gradle archs -map. For example, if your Halide installation was built without arm64-v8a, -remove it from APP_ABI and archs. Both list and map should match, otherwise you -will be getting compilation errors complaining about a missing -halide_generated.h file: - -``` -:ndkBuild FAILED - -FAILURE: Build failed with an exception. - -* What went wrong: -Execution failed for task ':ndkBuild'. -... - Output: - /private/tmp/7/halide/apps/HelloAndroidCamera2/jni/native.cpp:11:26: fatal error: deinterleave.h: No such file or directory - #include "deinterleave.h" - -``` - -# Android Studio - -To load project into Android Studio use "File/Import Project..." in Android -Studio and point to apps/HelloAndroidCamera2/build.gradle file. +(`Halide_ROOT` can also be provided via an environment variable of the same +name.) This produces `app/build/outputs/apk/debug/app-debug.apk`, installable +with `adb install`. -You will have to edit automatically-generated local.properties file to add -ndk.dir property so it points to your Android NDK installation as described in -Gradle section above. +To build in Android Studio instead, open this directory as a project, add +`Halide_ROOT=` to `gradle.properties` (or +`local.properties`), and use the Run button. diff --git a/apps/HelloAndroidCamera2/ant.properties b/apps/HelloAndroidCamera2/ant.properties deleted file mode 100644 index 0a93dd216454..000000000000 --- a/apps/HelloAndroidCamera2/ant.properties +++ /dev/null @@ -1,19 +0,0 @@ -# This file is used to override default values used by the Ant build system. -# -# This file must be checked into Version Control Systems, as it is -# integral to the build system of your project. - -# This file is only used by the Ant script. - -# You can use this to override default values such as -# 'source.dir' for the location of your java source folder and -# 'out.dir' for the location of your output folder. - -# You can also use it define how the release builds are signed by declaring -# the following properties: -# 'key.store' for the location of your keystore and -# 'key.alias' for the name of the key to use. -# The password will be asked during the build when you use the 'release' target. - -java.source=7 -java.target=7 diff --git a/apps/HelloAndroidCamera2/app/build.gradle b/apps/HelloAndroidCamera2/app/build.gradle new file mode 100644 index 000000000000..81a87d16c0fb --- /dev/null +++ b/apps/HelloAndroidCamera2/app/build.gradle @@ -0,0 +1,55 @@ +plugins { + id "com.android.application" +} + +def halideRoot = project.findProperty("Halide_ROOT") ?: System.getenv("Halide_ROOT") +if (halideRoot == null) { + throw new GradleException( + "Set -PHalide_ROOT= (or the Halide_ROOT " + + "environment variable) to point this build at a Halide installation." + ) +} + +android { + namespace = "com.example.helloandroidcamera2" + compileSdk = 37 + + defaultConfig { + applicationId = "com.example.helloandroidcamera2" + minSdk = 21 + targetSdk = 37 + versionCode = 1 + versionName = "1.0" + + ndk { + abiFilters.addAll("arm64-v8a", "x86_64") + } + + externalNativeBuild { + cmake { + arguments "-DCMAKE_PREFIX_PATH=${halideRoot}" + } + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + externalNativeBuild { + cmake { + path = "src/main/cpp/CMakeLists.txt" + } + } + + buildTypes { + release { + minifyEnabled = false + } + } +} + +dependencies { + implementation "androidx.core:core:1.13.1" +} diff --git a/apps/HelloAndroidCamera2/AndroidManifest.xml b/apps/HelloAndroidCamera2/app/src/main/AndroidManifest.xml similarity index 89% rename from apps/HelloAndroidCamera2/AndroidManifest.xml rename to apps/HelloAndroidCamera2/app/src/main/AndroidManifest.xml index 012b1eedb8e3..c5d3a515e036 100644 --- a/apps/HelloAndroidCamera2/AndroidManifest.xml +++ b/apps/HelloAndroidCamera2/app/src/main/AndroidManifest.xml @@ -12,12 +12,8 @@ limitations under the License. --> - + - diff --git a/apps/HelloAndroidCamera2/jni/AndroidBufferUtilities.cpp b/apps/HelloAndroidCamera2/app/src/main/cpp/AndroidBufferUtilities.cpp similarity index 100% rename from apps/HelloAndroidCamera2/jni/AndroidBufferUtilities.cpp rename to apps/HelloAndroidCamera2/app/src/main/cpp/AndroidBufferUtilities.cpp diff --git a/apps/HelloAndroidCamera2/jni/AndroidBufferUtilities.h b/apps/HelloAndroidCamera2/app/src/main/cpp/AndroidBufferUtilities.h similarity index 100% rename from apps/HelloAndroidCamera2/jni/AndroidBufferUtilities.h rename to apps/HelloAndroidCamera2/app/src/main/cpp/AndroidBufferUtilities.h diff --git a/apps/HelloAndroidCamera2/app/src/main/cpp/CMakeLists.txt b/apps/HelloAndroidCamera2/app/src/main/cpp/CMakeLists.txt new file mode 100644 index 000000000000..1e51931be389 --- /dev/null +++ b/apps/HelloAndroidCamera2/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,59 @@ +cmake_minimum_required(VERSION 3.28) +project(HelloAndroidCamera2) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED YES) +set(CMAKE_CXX_EXTENSIONS NO) + +# This file configures itself twice: once as a host build (to compile the +# generators) and once as this target build (driven by AGP's +# externalNativeBuild, under the NDK cross toolchain). See "Use +# add_halide_generator" in doc/HalideCMakePackage.md. +set(HelloAndroidCamera2-halide_generators_ROOT + "${CMAKE_CURRENT_SOURCE_DIR}/../../../.cxx-generators" +) +if (ANDROID) + # NO_CMAKE_FIND_ROOT_PATH: bypass the NDK toolchain's sysroot-only search. + find_program( + HelloAndroidCamera2_NATIVE_CXX REQUIRED + NAMES c++ clang++ g++ + NO_CMAKE_FIND_ROOT_PATH + ) + + execute_process( + COMMAND + ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR} -B + ${HelloAndroidCamera2-halide_generators_ROOT} + -DCMAKE_CXX_COMPILER=${HelloAndroidCamera2_NATIVE_CXX} + -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} + COMMAND_ERROR_IS_FATAL ANY + ) + + execute_process( + COMMAND ${CMAKE_COMMAND} --build ${HelloAndroidCamera2-halide_generators_ROOT} + COMMAND_ERROR_IS_FATAL ANY + ) +endif () + +# Halide is a host-built config package, not part of the Android sysroot. +find_package(Halide REQUIRED CMAKE_FIND_ROOT_PATH_BOTH) + +add_halide_generator(deinterleave_generator SOURCES generators/deinterleave_generator.cpp) +add_halide_generator(edge_detect_generator SOURCES generators/edge_detect_generator.cpp) + +if (NOT ANDROID) + # We're just building the Halide generators. + return() +endif () + +add_halide_library(deinterleave FROM HelloAndroidCamera2::halide_generators::deinterleave_generator) +add_halide_library(edge_detect FROM HelloAndroidCamera2::halide_generators::edge_detect_generator) + +add_library( + HelloAndroidCamera2 SHARED + AndroidBufferUtilities.cpp + HalideFilters.cpp + LockedSurface.cpp + YuvBufferT.cpp +) +target_link_libraries(HelloAndroidCamera2 PRIVATE deinterleave edge_detect log android atomic) diff --git a/apps/HelloAndroidCamera2/jni/HalideFilters.cpp b/apps/HelloAndroidCamera2/app/src/main/cpp/HalideFilters.cpp similarity index 100% rename from apps/HelloAndroidCamera2/jni/HalideFilters.cpp rename to apps/HelloAndroidCamera2/app/src/main/cpp/HalideFilters.cpp diff --git a/apps/HelloAndroidCamera2/jni/LockedSurface.cpp b/apps/HelloAndroidCamera2/app/src/main/cpp/LockedSurface.cpp similarity index 100% rename from apps/HelloAndroidCamera2/jni/LockedSurface.cpp rename to apps/HelloAndroidCamera2/app/src/main/cpp/LockedSurface.cpp diff --git a/apps/HelloAndroidCamera2/jni/LockedSurface.h b/apps/HelloAndroidCamera2/app/src/main/cpp/LockedSurface.h similarity index 100% rename from apps/HelloAndroidCamera2/jni/LockedSurface.h rename to apps/HelloAndroidCamera2/app/src/main/cpp/LockedSurface.h diff --git a/apps/HelloAndroidCamera2/jni/YuvBufferT.cpp b/apps/HelloAndroidCamera2/app/src/main/cpp/YuvBufferT.cpp similarity index 93% rename from apps/HelloAndroidCamera2/jni/YuvBufferT.cpp rename to apps/HelloAndroidCamera2/app/src/main/cpp/YuvBufferT.cpp index 1be6d755a8be..5cc96145af17 100644 --- a/apps/HelloAndroidCamera2/jni/YuvBufferT.cpp +++ b/apps/HelloAndroidCamera2/app/src/main/cpp/YuvBufferT.cpp @@ -78,11 +78,15 @@ YuvBufferT::YuvBufferT(uint8_t *lumaPointer, {0, chromaVHeight, chromaVRowStrideBytes}}; interleavedChromaView_ = Halide::Runtime::Buffer(chromaVPointer, 2, chromaShape); } else if (chromaStorage_ == ChromaStorage::kPlanarPackedUFirst) { - packedPlanarChromaView_ = chromaU_; - packedPlanarChromaView_.crop(1, 0, chromaUHeight * 2); + halide_dimension_t chromaShape[] = { + {0, chromaUWidth, chromaUElementStrideBytes}, + {0, chromaUHeight * 2, chromaURowStrideBytes}}; + packedPlanarChromaView_ = Halide::Runtime::Buffer(chromaUPointer, 2, chromaShape); } else if (chromaStorage_ == ChromaStorage::kPlanarPackedVFirst) { - packedPlanarChromaView_ = chromaV_; - packedPlanarChromaView_.crop(1, 0, chromaVHeight * 2); + halide_dimension_t chromaShape[] = { + {0, chromaVWidth, chromaVElementStrideBytes}, + {0, chromaVHeight * 2, chromaVRowStrideBytes}}; + packedPlanarChromaView_ = Halide::Runtime::Buffer(chromaVPointer, 2, chromaShape); } interleavedChromaView_.set_host_dirty(); diff --git a/apps/HelloAndroidCamera2/jni/YuvBufferT.h b/apps/HelloAndroidCamera2/app/src/main/cpp/YuvBufferT.h similarity index 100% rename from apps/HelloAndroidCamera2/jni/YuvBufferT.h rename to apps/HelloAndroidCamera2/app/src/main/cpp/YuvBufferT.h diff --git a/apps/HelloAndroidCamera2/jni/deinterleave_generator.cpp b/apps/HelloAndroidCamera2/app/src/main/cpp/generators/deinterleave_generator.cpp similarity index 100% rename from apps/HelloAndroidCamera2/jni/deinterleave_generator.cpp rename to apps/HelloAndroidCamera2/app/src/main/cpp/generators/deinterleave_generator.cpp diff --git a/apps/HelloAndroidCamera2/jni/edge_detect_generator.cpp b/apps/HelloAndroidCamera2/app/src/main/cpp/generators/edge_detect_generator.cpp similarity index 100% rename from apps/HelloAndroidCamera2/jni/edge_detect_generator.cpp rename to apps/HelloAndroidCamera2/app/src/main/cpp/generators/edge_detect_generator.cpp diff --git a/apps/HelloAndroidCamera2/src/com/android/ex/camera2/blocking/BlockingCameraManager.java b/apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/blocking/BlockingCameraManager.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/android/ex/camera2/blocking/BlockingCameraManager.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/blocking/BlockingCameraManager.java diff --git a/apps/HelloAndroidCamera2/src/com/android/ex/camera2/blocking/BlockingCaptureCallback.java b/apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/blocking/BlockingCaptureCallback.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/android/ex/camera2/blocking/BlockingCaptureCallback.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/blocking/BlockingCaptureCallback.java diff --git a/apps/HelloAndroidCamera2/src/com/android/ex/camera2/blocking/BlockingSessionCallback.java b/apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/blocking/BlockingSessionCallback.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/android/ex/camera2/blocking/BlockingSessionCallback.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/blocking/BlockingSessionCallback.java diff --git a/apps/HelloAndroidCamera2/src/com/android/ex/camera2/blocking/BlockingStateCallback.java b/apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/blocking/BlockingStateCallback.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/android/ex/camera2/blocking/BlockingStateCallback.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/blocking/BlockingStateCallback.java diff --git a/apps/HelloAndroidCamera2/src/com/android/ex/camera2/exceptions/TimeoutRuntimeException.java b/apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/exceptions/TimeoutRuntimeException.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/android/ex/camera2/exceptions/TimeoutRuntimeException.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/exceptions/TimeoutRuntimeException.java diff --git a/apps/HelloAndroidCamera2/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java b/apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/pos/AutoFocusStateMachine.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/pos/AutoFocusStateMachine.java diff --git a/apps/HelloAndroidCamera2/src/com/android/ex/camera2/utils/StateChangeListener.java b/apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/utils/StateChangeListener.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/android/ex/camera2/utils/StateChangeListener.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/utils/StateChangeListener.java diff --git a/apps/HelloAndroidCamera2/src/com/android/ex/camera2/utils/StateWaiter.java b/apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/utils/StateWaiter.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/android/ex/camera2/utils/StateWaiter.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/utils/StateWaiter.java diff --git a/apps/HelloAndroidCamera2/src/com/android/ex/camera2/utils/SysTrace.java b/apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/utils/SysTrace.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/android/ex/camera2/utils/SysTrace.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/android/ex/camera2/utils/SysTrace.java diff --git a/apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/AndroidBufferUtilities.java b/apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/AndroidBufferUtilities.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/AndroidBufferUtilities.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/AndroidBufferUtilities.java diff --git a/apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/AutoFitSurfaceView.java b/apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/AutoFitSurfaceView.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/AutoFitSurfaceView.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/AutoFitSurfaceView.java diff --git a/apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/Camera2BasicFragment.java b/apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/Camera2BasicFragment.java similarity index 99% rename from apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/Camera2BasicFragment.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/Camera2BasicFragment.java index 4e25fe66c25b..8ad7f1f9c973 100644 --- a/apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/Camera2BasicFragment.java +++ b/apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/Camera2BasicFragment.java @@ -485,11 +485,8 @@ private void createCameraPreviewSession() { @Override public void onClick(View view) { - switch (view.getId()) { - case R.id.toggle: { - mUseEdgeDetector = !mUseEdgeDetector; - break; - } + if (view.getId() == R.id.toggle) { + mUseEdgeDetector = !mUseEdgeDetector; } } diff --git a/apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/CameraActivity.java b/apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/CameraActivity.java new file mode 100644 index 000000000000..d50efda22782 --- /dev/null +++ b/apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/CameraActivity.java @@ -0,0 +1,60 @@ +/* + * Copyright 2014 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.example.helloandroidcamera2; + +import android.Manifest; +import android.app.Activity; +import android.content.pm.PackageManager; +import android.os.Bundle; + +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +public class CameraActivity extends Activity { + private static final int REQUEST_CAMERA_PERMISSION = 1; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_camera); + if (savedInstanceState == null) { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) + == PackageManager.PERMISSION_GRANTED) { + showCameraFragment(); + } else { + ActivityCompat.requestPermissions( + this, new String[] {Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); + } + } + } + + @Override + public void onRequestPermissionsResult( + int requestCode, String[] permissions, int[] grantResults) { + if (requestCode == REQUEST_CAMERA_PERMISSION + && grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + showCameraFragment(); + } + } + + private void showCameraFragment() { + getFragmentManager().beginTransaction() + .replace(R.id.container, Camera2BasicFragment.newInstance()) + .commit(); + } +} diff --git a/apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/HalideFilters.java b/apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/HalideFilters.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/HalideFilters.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/HalideFilters.java diff --git a/apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/HalideYuvBufferT.java b/apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/HalideYuvBufferT.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/HalideYuvBufferT.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/HalideYuvBufferT.java diff --git a/apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/NativeSurfaceHandle.java b/apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/NativeSurfaceHandle.java similarity index 100% rename from apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/NativeSurfaceHandle.java rename to apps/HelloAndroidCamera2/app/src/main/java/com/example/helloandroidcamera2/NativeSurfaceHandle.java diff --git a/apps/HelloAndroidCamera2/res/drawable-hdpi/ic_launcher.png b/apps/HelloAndroidCamera2/app/src/main/res/drawable-hdpi/ic_launcher.png similarity index 100% rename from apps/HelloAndroidCamera2/res/drawable-hdpi/ic_launcher.png rename to apps/HelloAndroidCamera2/app/src/main/res/drawable-hdpi/ic_launcher.png diff --git a/apps/HelloAndroidCamera2/res/drawable-ldpi/ic_launcher.png b/apps/HelloAndroidCamera2/app/src/main/res/drawable-ldpi/ic_launcher.png similarity index 100% rename from apps/HelloAndroidCamera2/res/drawable-ldpi/ic_launcher.png rename to apps/HelloAndroidCamera2/app/src/main/res/drawable-ldpi/ic_launcher.png diff --git a/apps/HelloAndroidCamera2/res/drawable-mdpi/ic_launcher.png b/apps/HelloAndroidCamera2/app/src/main/res/drawable-mdpi/ic_launcher.png similarity index 100% rename from apps/HelloAndroidCamera2/res/drawable-mdpi/ic_launcher.png rename to apps/HelloAndroidCamera2/app/src/main/res/drawable-mdpi/ic_launcher.png diff --git a/apps/HelloAndroidCamera2/res/drawable-xhdpi/ic_launcher.png b/apps/HelloAndroidCamera2/app/src/main/res/drawable-xhdpi/ic_launcher.png similarity index 100% rename from apps/HelloAndroidCamera2/res/drawable-xhdpi/ic_launcher.png rename to apps/HelloAndroidCamera2/app/src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/apps/HelloAndroidCamera2/res/layout/activity_camera.xml b/apps/HelloAndroidCamera2/app/src/main/res/layout/activity_camera.xml similarity index 100% rename from apps/HelloAndroidCamera2/res/layout/activity_camera.xml rename to apps/HelloAndroidCamera2/app/src/main/res/layout/activity_camera.xml diff --git a/apps/HelloAndroidCamera2/res/layout/fragment_camera2_basic.xml b/apps/HelloAndroidCamera2/app/src/main/res/layout/fragment_camera2_basic.xml similarity index 100% rename from apps/HelloAndroidCamera2/res/layout/fragment_camera2_basic.xml rename to apps/HelloAndroidCamera2/app/src/main/res/layout/fragment_camera2_basic.xml diff --git a/apps/HelloAndroidCamera2/res/layout/main.xml b/apps/HelloAndroidCamera2/app/src/main/res/layout/main.xml similarity index 100% rename from apps/HelloAndroidCamera2/res/layout/main.xml rename to apps/HelloAndroidCamera2/app/src/main/res/layout/main.xml diff --git a/apps/HelloAndroidCamera2/res/values/strings.xml b/apps/HelloAndroidCamera2/app/src/main/res/values/strings.xml similarity index 100% rename from apps/HelloAndroidCamera2/res/values/strings.xml rename to apps/HelloAndroidCamera2/app/src/main/res/values/strings.xml diff --git a/apps/HelloAndroidCamera2/res/values/styles.xml b/apps/HelloAndroidCamera2/app/src/main/res/values/styles.xml similarity index 100% rename from apps/HelloAndroidCamera2/res/values/styles.xml rename to apps/HelloAndroidCamera2/app/src/main/res/values/styles.xml diff --git a/apps/HelloAndroidCamera2/build-gradle.sh b/apps/HelloAndroidCamera2/build-gradle.sh deleted file mode 100755 index 5821b1e20e33..000000000000 --- a/apps/HelloAndroidCamera2/build-gradle.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -# Gradle needs to know where the NDK is. -# The easiest way is to set the ANDROID_NDK_HOME environment variable. -# Otherwise, set ndk.dir in local.properties (even though the file itself says -# that it's only used by ant). -# However, if you run "android update" (say, via build.sh), this variable will -# be clobbered. -./gradlew build && adb install -r gradle_build/outputs/apk/HelloAndroidCamera2-debug.apk && adb shell am start com.example.helloandroidcamera2/com.example.helloandroidcamera2.CameraActivity diff --git a/apps/HelloAndroidCamera2/build.gradle b/apps/HelloAndroidCamera2/build.gradle index 1689a03e8a59..f50bb1305913 100644 --- a/apps/HelloAndroidCamera2/build.gradle +++ b/apps/HelloAndroidCamera2/build.gradle @@ -1,176 +1,3 @@ -import org.apache.tools.ant.taskdefs.condition.Os - -// Avoid conflicts with Bazel on case-insensitive filesystems -buildDir = 'gradle_build' - -repositories { - jcenter() -} - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.2.2' - } - -} - -//////////////////////////////////////////////////////////////////////////////// -// Use gradle's native C++ plugin to build the Halide generator. -// -// sources: defines all the C++ source files. We only have one SourceSet called -// halide_generator. -// -// executables: we only make one binary called halide_generator. Here is where -// we pass compiler and linker flags. -// -// binaries.withType: binaries is a collection, which in our case is just the -// halide_generator executable. withType() filters the collection by type. -// binary is the iteration variable. -> defines the body of the lambda: -// for each binary: -// for each halide_target / Android ABI mapping: -// for each generator: -// run the generator with -g and target set -// make the later ndkBuild task depend on this task. - -apply plugin: "cpp" - -sources { - halide_generator { - cpp(CppSourceSet) { - source { - srcDirs "jni/" - include "deinterleave_generator.cpp" - include "edge_detect_generator.cpp" - } - source { - srcDirs "../../tools" - include "GenGen.cpp" - } - } - } -} - -executables { - halide_generator { - binaries.all { - cppCompiler.args "-std=c++17", "-g", "-Wall", "-fno-rtti", "-I", "${projectDir}/../../include", "-I", "${projectDir}/../../build/include" - // "/bin" assumes Makefile build for Halide; "/build/lib" assumes CMake build - linker.args "-lHalide", "-ldl", "-lpthread", "-lz", "-L", "${projectDir}/../../bin", "-L", "${projectDir}/../../build/lib" - } - } -} - -binaries.withType(NativeExecutableBinary) { binary -> - def bin = "${projectDir}/bin" - def linkTask = binary.tasks.link - println "linktask output file is " + linkTask.outputFile - Map archs = [ - // armeabi and armeabi-v7a are the same as far as Halide is concerned - "armeabi": "arm-32-android", - "armeabi-v7a": "arm-32-android", - "arm64-v8a": "arm-64-android", - "x86_64": "x86-64-android-sse41", - "x86": "x86-32-android" - ] - def generators = ["deinterleave", "edge_detect"] - archs.each { - arch -> println "creating task for: " + arch.key + " -> " + arch.value - def android_abi = arch.key - def hl_target = arch.value - def task_name = "generate_halide_binary_${binary.name.capitalize()}_${android_abi}" - def destDir = new File(bin, "${android_abi}") - def generateHalideTask = task(task_name) { - dependsOn linkTask - doFirst { - println "Executing: " + linkTask.outputFile + " ..." - destDir.mkdirs() - def envVars = [ "DYLD_LIBRARY_PATH=${projectDir}/../../bin", "LD_LIBRARY_PATH=${projectDir}/../../bin" ] - generators.each { generator -> - def proc = [linkTask.outputFile, "-g", generator, "-o", ".", "target=$hl_target"] - .execute(envVars, destDir) - proc.waitFor() - if (proc.exitValue() != 0) { - println "return code: ${proc.exitValue()}" - println "stderr: ${proc.err.text}" - println "stdout: ${proc.in.text}" - } - } - } - } - - // Call this task generateHalideTask. - binary.builtBy generateHalideTask - - // Tell gradle that the task called "ndkBuild" below depends - // on generateHalideTask. - ndkBuild.dependsOn generateHalideTask - } - println "done with archs" -} - - -//////////////////////////////////////////////////////////////////////////////// - -apply plugin: 'com.android.application' - -android { - compileSdkVersion 21 - buildToolsVersion "21.1.2" - - defaultConfig { - applicationId "com.example.helloandroidcamera2" - minSdkVersion 21 - targetSdkVersion 21 - versionCode 1 - versionName "1.0" - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - - sourceSets { - main { - java.srcDirs = ["src/"] - // Setting jni.srcDirs to [] disables the automatic ndk-build call - // which would use parameters defined in build.gradle. Use our own - // task (ndkBuild) below. - jni.srcDirs = [] - jniLibs.srcDirs = ["bin/lib/"] // default is src/main/jniLibs - manifest.srcFile "AndroidManifest.xml" - res.srcDirs = ["res/"] // default is src/main/res - } - } - - // Call regular ndk-build (ndk-build.cmd on Windows) script from - // app directory. - task ndkBuild(type: Exec) { - def ndkDir = project.android.ndkDirectory - def ndkBuildCmd = "" - if (Os.isFamily(Os.FAMILY_WINDOWS)) { - ndkBuildCmd = "ndk-build.cmd" - } else { - ndkBuildCmd = "ndk-build" - } - commandLine "$ndkDir/$ndkBuildCmd", "NDK_GEN_OUT=./bin/gen", "NDK_LIBS_OUT=./bin/lib", "NDK_OUT=./bin/obj" - } - - tasks.withType(JavaCompile) { - compileTask -> compileTask.dependsOn ndkBuild - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -task wrapper(type: Wrapper) { - gradleVersion = '2.2' +plugins { + id "com.android.application" version "9.3.0" apply false } diff --git a/apps/HelloAndroidCamera2/build.sh b/apps/HelloAndroidCamera2/build.sh deleted file mode 100755 index 808854e8c5d9..000000000000 --- a/apps/HelloAndroidCamera2/build.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -set -e -android update project -p . --subprojects --target android-21 -if [ -z "$ANDROID_NDK_HOME" ]; then - echo "Set ANDROID_NDK_HOME to point to your android ndk root directory" - exit 1 -fi - -mkdir -p bin - -c++ jni/edge_detect_generator.cpp ../../tools/GenGen.cpp \ - -g -fno-rtti -Wall -std=c++17 \ - -I ../../include -I ../../build/include \ - -L ../../bin -lHalide -ldl -lpthread -lz \ - -o bin/edge_detect_generator - -c++ jni/deinterleave_generator.cpp ../../tools/GenGen.cpp \ - -g -fno-rtti -Wall -std=c++17 \ - -I ../../include -I ../../build/include \ - -L ../../bin -lHalide -ldl -lpthread -lz \ - -o bin/deinterleave_generator - -for archs in arm-32-android,armeabi arm-32-android-armv7s,armeabi-v7a arm-64-android,arm64-v8a x86-64-android-sse41,x86_64 x86-32-android,x86; do - IFS=, - set $archs - HL_TARGET=$1 - ANDROID_ABI=$2 - mkdir -p bin/"$ANDROID_ABI" - ./bin/edge_detect_generator -g edge_detect -o bin/"$ANDROID_ABI" target="$HL_TARGET" - ./bin/deinterleave_generator -g deinterleave -o bin/"$ANDROID_ABI" target="$HL_TARGET" - unset IFS -done - -"${ANDROID_NDK_HOME}"/ndk-build NDK_GEN_OUT=./bin/gen NDK_LIBS_OUT=./bin/lib NDK_OUT=./bin/obj -ant debug -adb install -r bin/HelloAndroidCamera2-debug.apk -adb logcat diff --git a/apps/HelloAndroidCamera2/build.xml b/apps/HelloAndroidCamera2/build.xml deleted file mode 100644 index e5b2cc3c63fe..000000000000 --- a/apps/HelloAndroidCamera2/build.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/HelloAndroidCamera2/gradle.properties b/apps/HelloAndroidCamera2/gradle.properties new file mode 100644 index 000000000000..08df1c9e689b --- /dev/null +++ b/apps/HelloAndroidCamera2/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx2048m +android.useAndroidX=true diff --git a/apps/HelloAndroidCamera2/gradle/wrapper/gradle-wrapper.jar b/apps/HelloAndroidCamera2/gradle/wrapper/gradle-wrapper.jar index c97a8bdb9088..b1b8ef56b44f 100644 Binary files a/apps/HelloAndroidCamera2/gradle/wrapper/gradle-wrapper.jar and b/apps/HelloAndroidCamera2/gradle/wrapper/gradle-wrapper.jar differ diff --git a/apps/HelloAndroidCamera2/gradle/wrapper/gradle-wrapper.properties b/apps/HelloAndroidCamera2/gradle/wrapper/gradle-wrapper.properties index becb9e35aa5a..a9db11550c62 100644 --- a/apps/HelloAndroidCamera2/gradle/wrapper/gradle-wrapper.properties +++ b/apps/HelloAndroidCamera2/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,9 @@ -#Wed Jul 15 16:34:43 PDT 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip +networkTimeout=10000 +retries=0 +retryBackOffMs=500 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-all.zip diff --git a/apps/HelloAndroidCamera2/gradlew b/apps/HelloAndroidCamera2/gradlew index d7a2c7bbb98c..249efbb032ce 100755 --- a/apps/HelloAndroidCamera2/gradlew +++ b/apps/HelloAndroidCamera2/gradlew @@ -1,75 +1,128 @@ -#!/usr/bin/env bash +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# 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 +# +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# gradlew start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh gradlew +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum -warn ( ) { +warn () { echo "$*" -} +} >&2 -die ( ) { +die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false +msys=false darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -78,83 +131,118 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/apps/HelloAndroidCamera2/gradlew.bat b/apps/HelloAndroidCamera2/gradlew.bat index aec99730b4e8..8508ef684d4e 100644 --- a/apps/HelloAndroidCamera2/gradlew.bat +++ b/apps/HelloAndroidCamera2/gradlew.bat @@ -1,90 +1,82 @@ -@if "%DEBUG%" == "" @echo off +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants +if exist "%JAVA_EXE%" goto execute -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 -:mainEnd -if "%OS%"=="Windows_NT" endlocal +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/apps/HelloAndroidCamera2/jni/Android.mk b/apps/HelloAndroidCamera2/jni/Android.mk deleted file mode 100644 index 76b24675f996..000000000000 --- a/apps/HelloAndroidCamera2/jni/Android.mk +++ /dev/null @@ -1,21 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := HelloAndroidCamera2 -LOCAL_ARM_MODE := arm -LOCAL_SRC_FILES := \ - AndroidBufferUtilities.cpp \ - HalideFilters.cpp \ - LockedSurface.cpp \ - YuvBufferT.cpp -LOCAL_LDFLAGS := -L$(LOCAL_PATH)/../jni -LOCAL_LDLIBS := -lm -llog -landroid -latomic -LOCAL_LDLIBS += $(LOCAL_PATH)/../bin/$(TARGET_ARCH_ABI)/deinterleave.a -LOCAL_LDLIBS += $(LOCAL_PATH)/../bin/$(TARGET_ARCH_ABI)/edge_detect.a -LOCAL_STATIC_LIBRARIES := android_native_app_glue -LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../../build/include $(LOCAL_PATH)/../bin/$(TARGET_ARCH_ABI)/ - -include $(BUILD_SHARED_LIBRARY) - -$(call import-module,android/native_app_glue) diff --git a/apps/HelloAndroidCamera2/jni/Application.mk b/apps/HelloAndroidCamera2/jni/Application.mk deleted file mode 100644 index 0df61f392235..000000000000 --- a/apps/HelloAndroidCamera2/jni/Application.mk +++ /dev/null @@ -1,4 +0,0 @@ -APP_ABI := armeabi armeabi-v7a arm64-v8a x86_64 x86 -APP_PLATFORM := android-21 -APP_STL := c++_static -APP_CPPFLAGS := -std=c++17 -fno-rtti -fexceptions diff --git a/apps/HelloAndroidCamera2/settings.gradle b/apps/HelloAndroidCamera2/settings.gradle new file mode 100644 index 000000000000..88544e0e05ed --- /dev/null +++ b/apps/HelloAndroidCamera2/settings.gradle @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "HelloAndroidCamera2" +include(":app") diff --git a/apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/CameraActivity.java b/apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/CameraActivity.java deleted file mode 100644 index 8a2ce3d4a47d..000000000000 --- a/apps/HelloAndroidCamera2/src/com/example/helloandroidcamera2/CameraActivity.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2014 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.example.helloandroidcamera2; - -import android.app.Activity; -import android.os.Bundle; -import android.view.View; - -public class CameraActivity extends Activity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_camera); - if (savedInstanceState == null) { - getFragmentManager().beginTransaction() - .replace(R.id.container, Camera2BasicFragment.newInstance()) - .commit(); - } - } -} diff --git a/apps/support/android_smoke_test.sh b/apps/support/android_smoke_test.sh new file mode 100755 index 000000000000..333e5244e142 --- /dev/null +++ b/apps/support/android_smoke_test.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# +# Smoke-tests an Android camera app against a running emulator/device (adb +# must already see exactly the target device). Two phases: +# +# 1. Fresh install + launch, with the target permission NOT pre-granted: +# confirms the OS shows a runtime permission prompt. Apps that forget to +# request a dangerous permission at runtime (relying on the manifest +# declaration alone, which stopped being sufficient in Android 6.0) pass a +# build but fail this immediately. +# +# 2. Grant the permission, relaunch, and confirm the app stays alive with no +# fatal crash and none of a set of known-bad error signatures in logcat. +# This catches native-side bugs (bad buffer setup, out-of-bounds crops, +# etc.) that only manifest once real frames start flowing through the +# pipeline -- invisible to a build-only check. Deliberately does *not* +# require seeing a "pipeline completed" log line: whether the camera +# preview surface actually negotiates a size the pipeline runs on is +# sensitive to the emulator's screen/camera configuration, which varies +# across environments and isn't itself what regressed here. +set -euo pipefail + +if [ "$#" -lt 4 ]; then + echo "Usage: $0 [known-bad-pattern ...]" >&2 + exit 1 +fi + +apk=$1 +package=$2 +activity=$3 +permission=$4 +shift 4 +known_bad_patterns=("FATAL EXCEPTION" "Fatal signal" "$@") + +# Only one process can hold the (emulated) camera device at a time; make sure +# this app releases it on exit so a subsequent test for a different app isn't +# starved of a camera to open. +trap 'adb shell am force-stop "$package" >/dev/null 2>&1 || true' EXIT + +adb uninstall "$package" >/dev/null 2>&1 || true +adb install "$apk" + +echo "== Phase 1: confirm $package requests $permission at runtime ==" +adb shell am start -W -n "$package/$activity" +sleep 5 +top_activity=$(adb shell dumpsys activity activities | grep -m1 "topResumedActivity=") +if ! echo "$top_activity" | grep -q "permissioncontroller"; then + echo "FAIL: $package did not prompt for $permission on first launch" + echo "$top_activity" + exit 1 +fi +echo "OK: permission prompt shown" + +echo "== Phase 2: grant permission and confirm it runs with no known-bad symptoms ==" +adb shell pm grant "$package" "$permission" +adb logcat -c +adb shell am force-stop "$package" +adb shell am start -W -n "$package/$activity" +sleep 10 + +if ! adb shell pidof "$package" >/dev/null; then + echo "FAIL: $package is not running after launch (crashed?)" + adb logcat -d | tail -200 + exit 1 +fi + +logs=$(adb logcat -d) +pattern=$( + IFS='|' + echo "${known_bad_patterns[*]}" +) +if echo "$logs" | grep -qE "$pattern"; then + echo "FAIL: found a known-bad symptom in logcat for $package" + echo "$logs" | grep -B5 -A30 -E "$pattern" + exit 1 +fi + +echo "OK: $package ran with no known-bad symptoms"