Skip to content

Commit

Permalink
APL-VH-Android: July 2023 Release of APL 2023.2 compliant Viewhost Code
Browse files Browse the repository at this point in the history
  • Loading branch information
pranavsu1997 committed Jul 6, 2023
1 parent d2ad4bc commit 179863e
Show file tree
Hide file tree
Showing 8,445 changed files with 190,742 additions and 1,525,401 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Alexa Presentation Language (APL) ViewHost Android version 2023.1
# Alexa Presentation Language (APL) ViewHost Android version 2023.2

APLViewHostAndroid is a view host implementation for the Android Platform. It consists of
a thin JNI layer that interacts with APL Core Engine for component inflation and command
Expand Down
4 changes: 4 additions & 0 deletions apl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ add_library(
src/main/cpp/jniaudioplayer.cpp
src/main/cpp/jniaudioplayerfactory.cpp
src/main/cpp/jnicontent.cpp
src/main/cpp/jnidocumentcontext.cpp
src/main/cpp/jnidocumentmanager.cpp
src/main/cpp/jnidocumentsession.cpp
src/main/cpp/jniembeddeddocumentrequest.cpp
src/main/cpp/jniextensionclient.cpp
src/main/cpp/jniextensioncommand.cpp
src/main/cpp/jniextensioncomponent.cpp
Expand All @@ -66,6 +69,7 @@ add_library(
src/main/cpp/jnitextmeasurecallback.cpp
src/main/cpp/jnishadowblur.cpp
src/main/cpp/jninoisefilter.cpp
src/main/cpp/jnitext.cpp
)

# Specifies a path to native header files.
Expand Down
179 changes: 24 additions & 155 deletions apl/build.gradle
Original file line number Diff line number Diff line change
@@ -1,173 +1,42 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*/

apply plugin: 'com.android.library'
apply plugin: 'jacoco'
apply plugin: 'maven-publish'
// Top-level build file where you can add configuration options common to all sub-projects/modules.

jacoco {
toolVersion = '0.8.2'
}

tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}
def version = "1.10.0";

task jacocoTestReport(type: JacocoReport, dependsOn: ['test']) {
def mainSrc = "$project.projectDir/src/main/java"
project.buildDir = "build"

def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', '**/AutoValue_*.*']
def debugTree = fileTree(dir: "$project.buildDir/intermediates/javac/release/", excludes: fileFilter)
buildscript {

sourceDirectories.from(files([mainSrc]))
classDirectories.from(files(debugTree))

executionData.from(fileTree(dir: "$buildDir", includes: [
"jacoco/*.exec"
]))
reports {
xml.enabled = true
html.enabled = true
repositories {
google()
jcenter()
}
}

ext {
aplAndroidCmakeArgs = " -DCMAKE_VERBOSE_MAKEFILE=ON"
aplCoreDirCmakeArg = "-DAPL_CORE_DIR=" + projectDir + "/../../APLCoreEngine"
if (project.hasProperty('aplCoreDir')) {
aplCoreDirCmakeArg = "-DAPL_CORE_DIR=" + aplCoreDir
} else {
dependencies {
classpath 'com.android.tools.build:gradle:4.1.2'
classpath 'org.jacoco:org.jacoco.core:0.8.2'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

android {
compileSdkVersion 28
ndkVersion "23.0.7599858"
buildToolsVersion "30.0.2"
defaultConfig {
minSdkVersion 22
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: 'true'
renderscriptTargetApi 22
externalNativeBuild {
cmake {
// Sets optional flags for the C++ compiler.
// Enables RTTI (RunTime Type Information) support and C++ exceptions.
cppFlags "-std=c++11", "-frtti", "-fexceptions", "-DBUILD_ALEXAEXTENSIONS=On", "-DALEXAEXTENSIONS=1"
// Build the APL Core JNI library (excludes all other targets)
targets "apl", "apl-jni"
// Enable APL Core JNI build, and be verbose.
arguments aplCoreDirCmakeArg, aplAndroidCmakeArgs
}
}
ndk {
// Specifies the ABI configurations for the native libraries
// that Gradle will build and package with the APK.
abiFilters 'x86', 'armeabi-v7a', 'arm64-v8a'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
// minifyEnabled true
// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField("long", "VERSION_CODE", "${defaultConfig.versionCode}")
buildConfigField("String","VERSION_NAME","\"${defaultConfig.versionName}-core\"")
}
debug {
testCoverageEnabled true
debuggable true
aplAndroidCmakeArgs += " -DDEBUG_MEMORY_USE=ON"
buildConfigField("long", "VERSION_CODE", "${defaultConfig.versionCode}")
buildConfigField("String","VERSION_NAME","\"${defaultConfig.versionName}-core\"")
}
}
// Temporary fix until alpha10 - "More than one file was found with OS independent path 'META-INF/proguard/androidx-annotations.pro"
packagingOptions {
exclude 'META-INF/proguard/androidx-annotations.pro'
}

externalNativeBuild {
cmake {
version "3.10.2"

// Tells Gradle to find the root CMake APL build script. path is relative to
// the directory containing the module's build.gradle file. Gradle requires this
// build script to designate a CMake project as a build dependency and
// pull native sources into the Android project.
path "CMakeLists.txt"
}
}
lintOptions {
// If set to true, turns off analysis progress reporting by lint.
quiet false
// if set to true (default), stops the build if errors are found.
abortOnError true
// if true, only report errors.
ignoreWarnings false
// flag code marked for unreleasable
fatal 'StopShip'
disable 'LongLogTag'
allprojects {
if (System.getenv("MAINLINE_BUILD")) {
project.version = "${version}-SNAPSHOT"
} else {
project.version = "${version}." + (System.getenv("CODEBUILD_BUILD_NUMBER") ?: "0")
}
project.group = "APLViewhostAndroid"

testOptions {
animationsDisabled true

unitTests {
includeAndroidResources = true
}
repositories {
google()
jcenter()
}
}

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.annotation:annotation:1.0.0'
implementation 'androidx.core:core:1.0.0'
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation 'com.github.bumptech.glide:glide:4.6.1'
implementation project(':common')
implementation (project(':discovery')) { transitive = false }
testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:4.2'
testImplementation 'org.robolectric:shadows-httpclient:4.2'
testImplementation 'androidx.test:core:1.1.0'
testImplementation 'org.mockito:mockito-core:2.25.0'
androidTestImplementation 'org.mockito:mockito-core:2.25.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.annotation:annotation:1.0.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test:rules:1.1.1'
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
androidTestImplementation 'com.linkedin.dexmaker:dexmaker:2.25.0'
androidTestImplementation 'com.linkedin.dexmaker:dexmaker-mockito:2.25.0'
androidTestImplementation project(":commonTest")
androidTestUtil 'androidx.test:orchestrator:1.1.1'
api "com.google.auto.value:auto-value-annotations:1.7"
api 'com.google.guava:guava:27.0.1-jre'
annotationProcessor "com.google.auto.value:auto-value:1.7"
}

project.afterEvaluate {
// Dump configuration settings
println "APL CMake Args: " + aplAndroidCmakeArgs
println "APL Core Directory: " + aplCoreDirCmakeArg
println "Android SDK Directory: " + android.sdkDirectory.path
println "Android NDK Directory: " + android.ndkDirectory.path

// enforce native tools build runs first for enum dependencies
compileDebugJavaWithJavac.dependsOn externalNativeBuildDebug
compileReleaseJavaWithJavac.dependsOn externalNativeBuildRelease

tasks.test.finalizedBy(jacocoTestReport)
task clean(type: Delete) {
delete rootProject.buildDir
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
import org.junit.Before;
import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

Expand Down Expand Up @@ -410,4 +416,64 @@ public void testView_resizingText_RTL_anyWidth_usesNewLayout() {

assertNotEquals(actualLayout, originalLayout);
}

@Test
public void testView_updateTime_localTime_format() throws ParseException {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
String beforeDateString = formatter.format(new Date());
Date before = formatter.parse(beforeDateString);
onView(withId(com.amazon.apl.android.test.R.id.apl))
.perform(inflate("\"text\": \"${Time.format('DD-MM-YYYY hh:mm:ss', localTime)}\"", CHILD_LAYOUT_PROPERTIES))
.check(hasRootContext());

Layout originalLayout = getTestView().getLayout();
Date after = new Date();
Date actualDate = formatter.parse(originalLayout.getText().toString());
assertTrue(before.getTime() <= actualDate.getTime());
assertTrue(actualDate.getTime() <= after.getTime());
}

@Test
public void testView_updateTime_utcTime() {
Date before = new Date();
onView(withId(com.amazon.apl.android.test.R.id.apl))
.perform(inflate("\"text\": \"${utcTime}\"", CHILD_LAYOUT_PROPERTIES))
.check(hasRootContext());
Date after = new Date();

Layout originalLayout = getTestView().getLayout();
assertTrue(before.getTime() <= Long.parseLong(originalLayout.getText().toString()));
assertTrue(Long.parseLong(originalLayout.getText().toString()) <= after.getTime());
}

@Test
public void testView_updateTime_localTime() {
Date before = new Date();
onView(withId(com.amazon.apl.android.test.R.id.apl))
.perform(inflate("\"text\": \"${localTime}\"", CHILD_LAYOUT_PROPERTIES))
.check(hasRootContext());

Layout originalLayout = getTestView().getLayout();
Date after = new Date();
Date actualDate = new Date(Long.parseLong(originalLayout.getText().toString()));
Calendar now = Calendar.getInstance();
long offset = now.get(Calendar.ZONE_OFFSET) + now.get(Calendar.DST_OFFSET);
assertTrue(before.getTime() <= actualDate.getTime() - offset);
assertTrue(actualDate.getTime() - offset <= after.getTime());
}

@Test
public void testView_updateTime_elapsedTime() {
onView(withId(com.amazon.apl.android.test.R.id.apl))
.perform(inflate("\"text\": \"${elapsedTime}\"", CHILD_LAYOUT_PROPERTIES))
.check(hasRootContext());

Layout originalLayout = getTestView().getLayout();
assertEquals("0", originalLayout.getText().toString());
onView(isRoot())
.perform(waitFor(500));
Layout newLayout = getTestView().getLayout();
assertTrue( 400 <= Integer.parseInt(newLayout.getText().toString()));
assertTrue(Integer.parseInt(newLayout.getText().toString()) <= 600);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ private void verifySettersAndGetters(final FakeMediaPlayer fakeMediaPlayer,
fakeMediaPlayer.seek(currentSeekPosition);
assertEquals(currentTrackIndex, fakeMediaPlayer.getCurrentTrackIndex());
assertEquals(currentSeekPosition, fakeMediaPlayer.getCurrentSeekPosition());

fakeMediaPlayer.seekTo(currentSeekPosition);
assertEquals(currentSeekPosition, fakeMediaPlayer.getCurrentSeekPosition());
}

private void verifyAddMediaStateListener(FakeMediaPlayer fakeMediaPlayer,
Expand Down Expand Up @@ -370,6 +373,11 @@ public void seek(int msec) {
mCurrentSeekPosition = msec;
}

@Override
public void seekTo(int msec) {
seek(msec);
}

@Override
public void rewind() {

Expand Down
28 changes: 28 additions & 0 deletions apl/src/main/cpp/include/jnidocumentcontext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*/

#ifndef APLVIEWHOSTANDROID_JNIDOCUMENTCONTEXT_H
#define APLVIEWHOSTANDROID_JNIDOCUMENTCONTEXT_H
#include "apl/apl.h"

#ifdef __cplusplus
extern "C" {
#endif

namespace apl {
namespace jni {
/**
* Given a core DocumentContext, return a unique identifier for the underlying object.
* @param document The DocumentContext
* @return an opaque identifier or 0 if the provided document context is null
*/
jlong getDocumentContextId(const DocumentContextPtr document);

} // namespace jni
} // namespace apl

#ifdef __cplusplus
}
#endif
#endif //APLVIEWHOSTANDROID_JNIDOCUMENTCONTEXT_H
43 changes: 43 additions & 0 deletions apl/src/main/cpp/include/jnidocumentmanager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*/

#ifndef APLVIEWHOSTANDROID_JNIDOCUMENTMANAGER_H
#define APLVIEWHOSTANDROID_JNIDOCUMENTMANAGER_H
#include "apl/apl.h"

#ifdef __cplusplus
extern "C" {
#endif
/**
* Initialize and cache java class and method handles for callback to the rendering layer.
*/
jboolean documentmanager_OnLoad(JavaVM *vm, void *reserved __attribute__((__unused__)));

/**
* Release the class and method cache.
*/
void documentmanager_OnUnload(JavaVM *vm, void *reserved __attribute__((__unused__)));

namespace apl {
namespace jni {
class AndroidDocumentManager : public DocumentManager {
public:
AndroidDocumentManager() {}

virtual ~AndroidDocumentManager();
void setInstance(jobject instance);

void request(const std::weak_ptr<EmbedRequest>& request,
EmbedRequestSuccessCallback success,
EmbedRequestFailureCallback error) override;
private:
jweak mInstance;
};
} // namespace jni
} // namespace apl

#ifdef __cplusplus
}
#endif
#endif //APLVIEWHOSTANDROID_JNIDOCUMENTMANAGER_H

0 comments on commit 179863e

Please sign in to comment.