diff options
21 files changed, 960 insertions, 564 deletions
diff --git a/Android.bp b/Android.bp index 8e09157bb461..67902b310481 100644 --- a/Android.bp +++ b/Android.bp @@ -106,6 +106,7 @@ filegroup { ":android.security.maintenance-java-source", ":android.security.metrics-java-source", ":android.system.keystore2-V3-java-source", + ":android.hardware.cas-V1-java-source", ":credstore_aidl", ":dumpstate_aidl", ":framework_native_aidl", @@ -196,6 +197,7 @@ java_library { "updatable-driver-protos", "ota_metadata_proto_java", "android.hidl.base-V1.0-java", + "android.hardware.cas-V1-java", // AIDL "android.hardware.cas-V1.0-java", "android.hardware.cas-V1.1-java", "android.hardware.cas-V1.2-java", diff --git a/StubLibraries.bp b/StubLibraries.bp index 272b4f6e36e6..48c44c967ef0 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -378,6 +378,67 @@ java_library { }, } +java_library { + name: "android_stubs_private_jar", + defaults: ["android.jar_defaults"], + visibility: [ + "//visibility:override", + "//visibility:private", + ], + static_libs: [ + "stable.core.platform.api.stubs", + "core-lambda-stubs-for-system-modules", + "core-generated-annotation-stubs", + "framework", + "ext", + "framework-res-package-jar", + // The order of this matters, it has to be last to provide a + // package-private androidx.annotation.RecentlyNonNull without + // overriding the public android.annotation.Nullable in framework.jar + // with its own package-private android.annotation.Nullable. + "private-stub-annotations-jar", + ], +} + +java_genrule { + name: "android_stubs_private_hjar", + visibility: ["//visibility:private"], + srcs: [":android_stubs_private_jar{.hjar}"], + out: ["android_stubs_private.jar"], + cmd: "cp $(in) $(out)", +} + +java_library { + name: "android_stubs_private", + defaults: ["android_stubs_dists_default"], + visibility: ["//visibility:private"], + sdk_version: "none", + system_modules: "none", + static_libs: ["android_stubs_private_hjar"], + dist: { + dir: "apistubs/android/private", + }, +} + +java_genrule { + name: "android_stubs_private_framework_aidl", + visibility: ["//visibility:private"], + tools: ["sdkparcelables"], + srcs: [":android_stubs_private"], + out: ["framework.aidl"], + cmd: "rm -f $(genDir)/framework.aidl.merged && " + + "for i in $(in); do " + + " rm -f $(genDir)/framework.aidl.tmp && " + + " $(location sdkparcelables) $$i $(genDir)/framework.aidl.tmp && " + + " cat $(genDir)/framework.aidl.tmp >> $(genDir)/framework.aidl.merged; " + + "done && " + + "sort -u $(genDir)/framework.aidl.merged > $(out)", + dist: { + targets: ["sdk"], + dir: "apistubs/android/private", + }, +} + //////////////////////////////////////////////////////////////////////// // api-versions.xml generation, for public and system. This API database // also contains the android.test.* APIs. diff --git a/core/api/current.txt b/core/api/current.txt index f1b82da7fb0a..a0c132f980dc 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -17088,8 +17088,8 @@ package android.hardware { method public boolean flush(android.hardware.SensorEventListener); method public static float getAltitude(float, float); method public static void getAngleChange(float[], float[], float[]); - method public android.hardware.Sensor getDefaultSensor(int); - method public android.hardware.Sensor getDefaultSensor(int, boolean); + method @Nullable public android.hardware.Sensor getDefaultSensor(int); + method @Nullable public android.hardware.Sensor getDefaultSensor(int, boolean); method public java.util.List<android.hardware.Sensor> getDynamicSensorList(int); method public static float getInclination(float[]); method public static float[] getOrientation(float[], float[]); @@ -21142,6 +21142,7 @@ package android.media { field public static final int PLUGIN_STATUS_PHYSICAL_MODULE_CHANGED = 0; // 0x0 field public static final int PLUGIN_STATUS_SESSION_NUMBER_CHANGED = 1; // 0x1 field public static final int SCRAMBLING_MODE_AES128 = 9; // 0x9 + field public static final int SCRAMBLING_MODE_AES_CBC = 14; // 0xe field public static final int SCRAMBLING_MODE_AES_ECB = 10; // 0xa field public static final int SCRAMBLING_MODE_AES_SCTE52 = 11; // 0xb field public static final int SCRAMBLING_MODE_DVB_CISSA_V1 = 6; // 0x6 @@ -30767,8 +30768,7 @@ package android.opengl { method public static void scaleM(float[], int, float, float, float); method public static void setIdentityM(float[], int); method public static void setLookAtM(float[], int, float, float, float, float, float, float, float, float, float); - method @Deprecated public static void setRotateEulerM(float[], int, float, float, float); - method public static void setRotateEulerM2(@NonNull float[], int, float, float, float); + method public static void setRotateEulerM(float[], int, float, float, float); method public static void setRotateM(float[], int, float, float, float, float); method public static void translateM(float[], int, float[], int, float, float, float); method public static void translateM(float[], int, float, float, float); diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index dec424c3ad7a..6d8c4a93b44e 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -16,6 +16,7 @@ package android.hardware; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.SystemService; import android.compat.annotation.UnsupportedAppUsage; @@ -496,7 +497,7 @@ public abstract class SensorManager { * @see #getSensorList(int) * @see Sensor */ - public Sensor getDefaultSensor(int type) { + public @Nullable Sensor getDefaultSensor(int type) { // TODO: need to be smarter, for now, just return the 1st sensor List<Sensor> l = getSensorList(type); boolean wakeUpSensor = false; @@ -544,7 +545,7 @@ public abstract class SensorManager { * and the application has the necessary permissions, or null otherwise. * @see Sensor#isWakeUpSensor() */ - public Sensor getDefaultSensor(int type, boolean wakeUp) { + public @Nullable Sensor getDefaultSensor(int type, boolean wakeUp) { List<Sensor> l = getSensorList(type); for (Sensor sensor : l) { if (sensor.isWakeUpSensor() == wakeUp) { diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 468e6041eb73..5abe677d0e1f 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -88,8 +88,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Map; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -1027,6 +1027,19 @@ public class CameraMetadataNative implements Parcelable { return fixedFaceRectangles; } + private boolean setLensShadingMap(LensShadingMap lensShadingMap) { + if (lensShadingMap == null) { + return false; + } + float[] lsmArray = new float[lensShadingMap.getGainFactorCount()]; + lensShadingMap.copyGainFactors(lsmArray, 0); + setBase(CaptureResult.STATISTICS_LENS_SHADING_MAP, lsmArray); + + Size s = new Size(lensShadingMap.getRowCount(), lensShadingMap.getColumnCount()); + setBase(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE, s); + return true; + } + private LensShadingMap getLensShadingMap() { float[] lsmArray = getBase(CaptureResult.STATISTICS_LENS_SHADING_MAP); Size s = get(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE); @@ -1851,6 +1864,13 @@ public class CameraMetadataNative implements Parcelable { metadata.setAERegions(value); } }); + sSetCommandMap.put(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP.getNativeKey(), + new SetCommand() { + @Override + public <T> void setValue(CameraMetadataNative metadata, T value) { + metadata.setLensShadingMap((LensShadingMap) value); + } + }); } private boolean setAvailableFormats(int[] value) { diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp index 1c6c95f389aa..d8522658d747 100644 --- a/core/jni/android/opengl/util.cpp +++ b/core/jni/android/opengl/util.cpp @@ -541,6 +541,87 @@ jint util_visibilityTest(JNIEnv *env, jclass clazz, indices.mData, indexCount); } +#define I(_i, _j) ((_j)+ 4*(_i)) + +static +void multiplyMM(float* r, const float* lhs, const float* rhs) +{ + for (int i=0 ; i<4 ; i++) { + const float rhs_i0 = rhs[ I(i,0) ]; + float ri0 = lhs[ I(0,0) ] * rhs_i0; + float ri1 = lhs[ I(0,1) ] * rhs_i0; + float ri2 = lhs[ I(0,2) ] * rhs_i0; + float ri3 = lhs[ I(0,3) ] * rhs_i0; + for (int j=1 ; j<4 ; j++) { + const float rhs_ij = rhs[ I(i,j) ]; + ri0 += lhs[ I(j,0) ] * rhs_ij; + ri1 += lhs[ I(j,1) ] * rhs_ij; + ri2 += lhs[ I(j,2) ] * rhs_ij; + ri3 += lhs[ I(j,3) ] * rhs_ij; + } + r[ I(i,0) ] = ri0; + r[ I(i,1) ] = ri1; + r[ I(i,2) ] = ri2; + r[ I(i,3) ] = ri3; + } +} + +static +void util_multiplyMM(JNIEnv *env, jclass clazz, + jfloatArray result_ref, jint resultOffset, + jfloatArray lhs_ref, jint lhsOffset, + jfloatArray rhs_ref, jint rhsOffset) { + + FloatArrayHelper resultMat(env, result_ref, resultOffset, 16); + FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16); + FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 16); + + bool checkOK = resultMat.check() && lhs.check() && rhs.check(); + + if ( !checkOK ) { + return; + } + + resultMat.bind(); + lhs.bind(); + rhs.bind(); + + multiplyMM(resultMat.mData, lhs.mData, rhs.mData); + + resultMat.commitChanges(); +} + +static +void multiplyMV(float* r, const float* lhs, const float* rhs) +{ + mx4transform(rhs[0], rhs[1], rhs[2], rhs[3], lhs, r); +} + +static +void util_multiplyMV(JNIEnv *env, jclass clazz, + jfloatArray result_ref, jint resultOffset, + jfloatArray lhs_ref, jint lhsOffset, + jfloatArray rhs_ref, jint rhsOffset) { + + FloatArrayHelper resultV(env, result_ref, resultOffset, 4); + FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16); + FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 4); + + bool checkOK = resultV.check() && lhs.check() && rhs.check(); + + if ( !checkOK ) { + return; + } + + resultV.bind(); + lhs.bind(); + rhs.bind(); + + multiplyMV(resultV.mData, lhs.mData, rhs.mData); + + resultV.commitChanges(); +} + // --------------------------------------------------------------------------- // The internal format is no longer the same as pixel format, per Table 2 in @@ -928,6 +1009,11 @@ static jint etc1_getHeight(JNIEnv *env, jclass clazz, * JNI registration */ +static const JNINativeMethod gMatrixMethods[] = { + { "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM }, + { "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV }, +}; + static const JNINativeMethod gVisibilityMethods[] = { { "computeBoundingSphere", "([FII[FI)V", (void*)util_computeBoundingSphere }, { "frustumCullSpheres", "([FI[FII[III)I", (void*)util_frustumCullSpheres }, @@ -960,6 +1046,7 @@ typedef struct _ClassRegistrationInfo { } ClassRegistrationInfo; static const ClassRegistrationInfo gClasses[] = { + {"android/opengl/Matrix", gMatrixMethods, NELEM(gMatrixMethods)}, {"android/opengl/Visibility", gVisibilityMethods, NELEM(gVisibilityMethods)}, {"android/opengl/GLUtils", gUtilsMethods, NELEM(gUtilsMethods)}, {"android/opengl/ETC1", gEtc1Methods, NELEM(gEtc1Methods)}, diff --git a/core/tests/coretests/src/android/hardware/camera2/OWNERS b/core/tests/coretests/src/android/hardware/camera2/OWNERS new file mode 100644 index 000000000000..f48a95c5b3a3 --- /dev/null +++ b/core/tests/coretests/src/android/hardware/camera2/OWNERS @@ -0,0 +1 @@ +include platform/frameworks/av:/camera/OWNERS diff --git a/core/tests/coretests/src/android/hardware/camera2/impl/CaptureMetadataNativeTest.java b/core/tests/coretests/src/android/hardware/camera2/impl/CaptureMetadataNativeTest.java new file mode 100644 index 000000000000..a38c040c7746 --- /dev/null +++ b/core/tests/coretests/src/android/hardware/camera2/impl/CaptureMetadataNativeTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2023 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 android.hardware.camera2.impl; + +import static com.google.common.truth.Truth.assertThat; + +import android.hardware.camera2.CaptureResult; +import android.hardware.camera2.params.LensShadingMap; +import android.util.Size; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.Arrays; + +@SmallTest +@RunWith(JUnit4.class) +/** Tests for {@link CameraMetadataNative} class. */ +public class CaptureMetadataNativeTest { + + @Test + public void setLensShadingMap() { + final Size s = new Size(10, 10); + // 4 x rows x columns + final float[] elements = new float[400]; + Arrays.fill(elements, 42); + + final LensShadingMap lensShadingMap = + new LensShadingMap(elements, s.getHeight(), s.getWidth()); + CameraMetadataNative captureResults = new CameraMetadataNative(); + captureResults.set(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP, lensShadingMap); + + final LensShadingMap output = + captureResults.get(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP); + + assertThat(output).isEqualTo(lensShadingMap); + } +} diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index c0220879094a..2800e3148988 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -634,7 +634,7 @@ cc_library_static { cc_defaults { name: "hwui_test_defaults", defaults: ["hwui_defaults"], - test_suites: ["device-tests"], + test_suites: ["general-tests"], header_libs: ["libandroid_headers_private"], target: { android: { diff --git a/libs/hwui/AndroidTest.xml b/libs/hwui/AndroidTest.xml index 381fb9f6c7bf..911315f81a8a 100644 --- a/libs/hwui/AndroidTest.xml +++ b/libs/hwui/AndroidTest.xml @@ -16,22 +16,22 @@ <configuration description="Config for hwuimicro"> <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> <option name="cleanup" value="true" /> - <option name="push" value="hwui_unit_tests->/data/nativetest/hwui_unit_tests" /> - <option name="push" value="hwuimicro->/data/benchmarktest/hwuimicro" /> - <option name="push" value="hwuimacro->/data/benchmarktest/hwuimacro" /> + <option name="push" value="hwui_unit_tests->/data/local/tmp/nativetest/hwui_unit_tests" /> + <option name="push" value="hwuimicro->/data/local/tmp/benchmarktest/hwuimicro" /> + <option name="push" value="hwuimacro->/data/local/tmp/benchmarktest/hwuimacro" /> </target_preparer> <option name="test-suite-tag" value="apct" /> <test class="com.android.tradefed.testtype.GTest" > - <option name="native-test-device-path" value="/data/nativetest" /> + <option name="native-test-device-path" value="/data/local/tmp/nativetest" /> <option name="module-name" value="hwui_unit_tests" /> </test> <test class="com.android.tradefed.testtype.GoogleBenchmarkTest" > - <option name="native-benchmark-device-path" value="/data/benchmarktest" /> + <option name="native-benchmark-device-path" value="/data/local/tmp/benchmarktest" /> <option name="benchmark-module-name" value="hwuimicro" /> <option name="file-exclusion-filter-regex" value=".*\.config$" /> </test> <test class="com.android.tradefed.testtype.GoogleBenchmarkTest" > - <option name="native-benchmark-device-path" value="/data/benchmarktest" /> + <option name="native-benchmark-device-path" value="/data/local/tmp/benchmarktest" /> <option name="benchmark-module-name" value="hwuimacro" /> <option name="file-exclusion-filter-regex" value=".*\.config$" /> </test> diff --git a/libs/hwui/TEST_MAPPING b/libs/hwui/TEST_MAPPING index b1719a979ce5..03682e82e28d 100644 --- a/libs/hwui/TEST_MAPPING +++ b/libs/hwui/TEST_MAPPING @@ -5,6 +5,9 @@ }, { "name": "CtsAccelerationTestCases" + }, + { + "name": "hwui_unit_tests" } ], "imports": [ diff --git a/libs/hwui/tests/unit/CacheManagerTests.cpp b/libs/hwui/tests/unit/CacheManagerTests.cpp index edd3e4e4f4d4..fc84abb1d605 100644 --- a/libs/hwui/tests/unit/CacheManagerTests.cpp +++ b/libs/hwui/tests/unit/CacheManagerTests.cpp @@ -32,7 +32,8 @@ static size_t getCacheUsage(GrDirectContext* grContext) { return cacheUsage; } -RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, trimMemory) { +// TOOD(258700630): fix this test and re-enable +RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, DISABLED_trimMemory) { int32_t width = DeviceInfo::get()->getWidth(); int32_t height = DeviceInfo::get()->getHeight(); GrDirectContext* grContext = renderThread.getGrContext(); diff --git a/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp b/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp index 098b4ccea8cf..c2d23e6d1101 100644 --- a/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp +++ b/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp @@ -14,17 +14,18 @@ * limitations under the License. */ +#include <android-base/macros.h> +#include <gmock/gmock.h> #include <gtest/gtest.h> - -#include "protos/graphicsstats.pb.h" -#include "service/GraphicsStatsService.h" - #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> +#include "protos/graphicsstats.pb.h" +#include "service/GraphicsStatsService.h" + using namespace android; using namespace android::uirenderer; @@ -49,12 +50,14 @@ std::string findRootPath() { // No code left untested TEST(GraphicsStats, findRootPath) { -#ifdef __LP64__ - std::string expected = "/data/nativetest64/hwui_unit_tests"; -#else - std::string expected = "/data/nativetest/hwui_unit_tests"; -#endif - EXPECT_EQ(expected, findRootPath()); + // Different tools/infrastructure seem to push this to different locations. It shouldn't really + // matter where the binary is, so add new locations here as needed. This test still seems good + // as it's nice to understand the possibility space, and ensure findRootPath continues working + // as expected. + std::string acceptableLocations[] = {"/data/nativetest/hwui_unit_tests", + "/data/nativetest64/hwui_unit_tests", + "/data/local/tmp/nativetest/hwui_unit_tests/" ABI_STRING}; + EXPECT_THAT(acceptableLocations, ::testing::Contains(findRootPath())); } TEST(GraphicsStats, saveLoad) { diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java index 582a28ee278e..015602e95533 100644 --- a/media/java/android/media/MediaCas.java +++ b/media/java/android/media/MediaCas.java @@ -21,11 +21,12 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.content.Context; +import android.hardware.cas.AidlCasPluginDescriptor; +import android.hardware.cas.ICas; +import android.hardware.cas.ICasListener; +import android.hardware.cas.IMediaCasService; +import android.hardware.cas.Status; import android.hardware.cas.V1_0.HidlCasPluginDescriptor; -import android.hardware.cas.V1_0.ICas; -import android.hardware.cas.V1_0.IMediaCasService; -import android.hardware.cas.V1_2.ICasListener; -import android.hardware.cas.V1_2.Status; import android.media.MediaCasException.*; import android.media.tv.TvInputService.PriorityHintUseCaseType; import android.media.tv.tunerresourcemanager.CasSessionRequest; @@ -39,6 +40,7 @@ import android.os.Looper; import android.os.Message; import android.os.Process; import android.os.RemoteException; +import android.os.ServiceManager; import android.util.Log; import android.util.Singleton; @@ -47,6 +49,7 @@ import com.android.internal.util.FrameworkStatsLog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -114,9 +117,10 @@ import java.util.Objects; */ public final class MediaCas implements AutoCloseable { private static final String TAG = "MediaCas"; - private ICas mICas; - private android.hardware.cas.V1_1.ICas mICasV11; - private android.hardware.cas.V1_2.ICas mICasV12; + private ICas mICas = null; + private android.hardware.cas.V1_0.ICas mICasHidl = null; + private android.hardware.cas.V1_1.ICas mICasHidl11 = null; + private android.hardware.cas.V1_2.ICas mICasHidl12 = null; private EventListener mListener; private HandlerThread mHandlerThread; private EventHandler mEventHandler; @@ -133,88 +137,84 @@ public final class MediaCas implements AutoCloseable { * * @hide */ - @IntDef(prefix = "SCRAMBLING_MODE_", - value = {SCRAMBLING_MODE_RESERVED, SCRAMBLING_MODE_DVB_CSA1, SCRAMBLING_MODE_DVB_CSA2, - SCRAMBLING_MODE_DVB_CSA3_STANDARD, - SCRAMBLING_MODE_DVB_CSA3_MINIMAL, SCRAMBLING_MODE_DVB_CSA3_ENHANCE, - SCRAMBLING_MODE_DVB_CISSA_V1, SCRAMBLING_MODE_DVB_IDSA, - SCRAMBLING_MODE_MULTI2, SCRAMBLING_MODE_AES128, SCRAMBLING_MODE_AES_ECB, - SCRAMBLING_MODE_AES_SCTE52, SCRAMBLING_MODE_TDES_ECB, SCRAMBLING_MODE_TDES_SCTE52}) + @IntDef( + prefix = "SCRAMBLING_MODE_", + value = { + SCRAMBLING_MODE_RESERVED, + SCRAMBLING_MODE_DVB_CSA1, + SCRAMBLING_MODE_DVB_CSA2, + SCRAMBLING_MODE_DVB_CSA3_STANDARD, + SCRAMBLING_MODE_DVB_CSA3_MINIMAL, + SCRAMBLING_MODE_DVB_CSA3_ENHANCE, + SCRAMBLING_MODE_DVB_CISSA_V1, + SCRAMBLING_MODE_DVB_IDSA, + SCRAMBLING_MODE_MULTI2, + SCRAMBLING_MODE_AES128, + SCRAMBLING_MODE_AES_CBC, + SCRAMBLING_MODE_AES_ECB, + SCRAMBLING_MODE_AES_SCTE52, + SCRAMBLING_MODE_TDES_ECB, + SCRAMBLING_MODE_TDES_SCTE52 + }) @Retention(RetentionPolicy.SOURCE) public @interface ScramblingMode {} - /** - * DVB (Digital Video Broadcasting) reserved mode. - */ - public static final int SCRAMBLING_MODE_RESERVED = - android.hardware.cas.V1_2.ScramblingMode.RESERVED; - /** - * DVB (Digital Video Broadcasting) Common Scrambling Algorithm (CSA) 1. - */ - public static final int SCRAMBLING_MODE_DVB_CSA1 = - android.hardware.cas.V1_2.ScramblingMode.DVB_CSA1; - /** - * DVB CSA 2. - */ - public static final int SCRAMBLING_MODE_DVB_CSA2 = - android.hardware.cas.V1_2.ScramblingMode.DVB_CSA2; - /** - * DVB CSA 3 in standard mode. - */ + /** DVB (Digital Video Broadcasting) reserved mode. */ + public static final int SCRAMBLING_MODE_RESERVED = android.hardware.cas.ScramblingMode.RESERVED; + + /** DVB (Digital Video Broadcasting) Common Scrambling Algorithm (CSA) 1. */ + public static final int SCRAMBLING_MODE_DVB_CSA1 = android.hardware.cas.ScramblingMode.DVB_CSA1; + + /** DVB CSA 2. */ + public static final int SCRAMBLING_MODE_DVB_CSA2 = android.hardware.cas.ScramblingMode.DVB_CSA2; + + /** DVB CSA 3 in standard mode. */ public static final int SCRAMBLING_MODE_DVB_CSA3_STANDARD = - android.hardware.cas.V1_2.ScramblingMode.DVB_CSA3_STANDARD; - /** - * DVB CSA 3 in minimally enhanced mode. - */ + android.hardware.cas.ScramblingMode.DVB_CSA3_STANDARD; + + /** DVB CSA 3 in minimally enhanced mode. */ public static final int SCRAMBLING_MODE_DVB_CSA3_MINIMAL = - android.hardware.cas.V1_2.ScramblingMode.DVB_CSA3_MINIMAL; - /** - * DVB CSA 3 in fully enhanced mode. - */ + android.hardware.cas.ScramblingMode.DVB_CSA3_MINIMAL; + + /** DVB CSA 3 in fully enhanced mode. */ public static final int SCRAMBLING_MODE_DVB_CSA3_ENHANCE = - android.hardware.cas.V1_2.ScramblingMode.DVB_CSA3_ENHANCE; - /** - * DVB Common IPTV Software-oriented Scrambling Algorithm (CISSA) Version 1. - */ + android.hardware.cas.ScramblingMode.DVB_CSA3_ENHANCE; + + /** DVB Common IPTV Software-oriented Scrambling Algorithm (CISSA) Version 1. */ public static final int SCRAMBLING_MODE_DVB_CISSA_V1 = - android.hardware.cas.V1_2.ScramblingMode.DVB_CISSA_V1; - /** - * ATIS-0800006 IIF Default Scrambling Algorithm (IDSA). - */ - public static final int SCRAMBLING_MODE_DVB_IDSA = - android.hardware.cas.V1_2.ScramblingMode.DVB_IDSA; - /** - * A symmetric key algorithm. - */ - public static final int SCRAMBLING_MODE_MULTI2 = - android.hardware.cas.V1_2.ScramblingMode.MULTI2; - /** - * Advanced Encryption System (AES) 128-bit Encryption mode. - */ - public static final int SCRAMBLING_MODE_AES128 = - android.hardware.cas.V1_2.ScramblingMode.AES128; - /** - * Advanced Encryption System (AES) Electronic Code Book (ECB) mode. - */ - public static final int SCRAMBLING_MODE_AES_ECB = - android.hardware.cas.V1_2.ScramblingMode.AES_ECB; + android.hardware.cas.ScramblingMode.DVB_CISSA_V1; + + /** ATIS-0800006 IIF Default Scrambling Algorithm (IDSA). */ + public static final int SCRAMBLING_MODE_DVB_IDSA = android.hardware.cas.ScramblingMode.DVB_IDSA; + + /** A symmetric key algorithm. */ + public static final int SCRAMBLING_MODE_MULTI2 = android.hardware.cas.ScramblingMode.MULTI2; + + /** Advanced Encryption System (AES) 128-bit Encryption mode. */ + public static final int SCRAMBLING_MODE_AES128 = android.hardware.cas.ScramblingMode.AES128; + + /** Advanced Encryption System (AES) Cipher Block Chaining (CBC) mode. */ + public static final int SCRAMBLING_MODE_AES_CBC = android.hardware.cas.ScramblingMode.AES_CBC; + + /** Advanced Encryption System (AES) Electronic Code Book (ECB) mode. */ + public static final int SCRAMBLING_MODE_AES_ECB = android.hardware.cas.ScramblingMode.AES_ECB; + /** * Advanced Encryption System (AES) Society of Cable Telecommunications Engineers (SCTE) 52 * mode. */ public static final int SCRAMBLING_MODE_AES_SCTE52 = - android.hardware.cas.V1_2.ScramblingMode.AES_SCTE52; - /** - * Triple Data Encryption Algorithm (TDES) Electronic Code Book (ECB) mode. - */ - public static final int SCRAMBLING_MODE_TDES_ECB = - android.hardware.cas.V1_2.ScramblingMode.TDES_ECB; + android.hardware.cas.ScramblingMode.AES_SCTE52; + + /** Triple Data Encryption Algorithm (TDES) Electronic Code Book (ECB) mode. */ + public static final int SCRAMBLING_MODE_TDES_ECB = android.hardware.cas.ScramblingMode.TDES_ECB; + /** * Triple Data Encryption Algorithm (TDES) Society of Cable Telecommunications Engineers (SCTE) * 52 mode. */ public static final int SCRAMBLING_MODE_TDES_SCTE52 = - android.hardware.cas.V1_2.ScramblingMode.TDES_SCTE52; + android.hardware.cas.ScramblingMode.TDES_SCTE52; /** * Usages used to open cas sessions. @@ -226,25 +226,21 @@ public final class MediaCas implements AutoCloseable { SESSION_USAGE_TIMESHIFT}) @Retention(RetentionPolicy.SOURCE) public @interface SessionUsage {} - /** - * Cas session is used to descramble live streams. - */ - public static final int SESSION_USAGE_LIVE = android.hardware.cas.V1_2.SessionIntent.LIVE; - /** - * Cas session is used to descramble recoreded streams. - */ - public static final int SESSION_USAGE_PLAYBACK = - android.hardware.cas.V1_2.SessionIntent.PLAYBACK; - /** - * Cas session is used to descramble live streams and encrypt local recorded content - */ - public static final int SESSION_USAGE_RECORD = android.hardware.cas.V1_2.SessionIntent.RECORD; + + /** Cas session is used to descramble live streams. */ + public static final int SESSION_USAGE_LIVE = android.hardware.cas.SessionIntent.LIVE; + + /** Cas session is used to descramble recoreded streams. */ + public static final int SESSION_USAGE_PLAYBACK = android.hardware.cas.SessionIntent.PLAYBACK; + + /** Cas session is used to descramble live streams and encrypt local recorded content */ + public static final int SESSION_USAGE_RECORD = android.hardware.cas.SessionIntent.RECORD; + /** * Cas session is used to descramble live streams , encrypt local recorded content and playback * local encrypted content. */ - public static final int SESSION_USAGE_TIMESHIFT = - android.hardware.cas.V1_2.SessionIntent.TIMESHIFT; + public static final int SESSION_USAGE_TIMESHIFT = android.hardware.cas.SessionIntent.TIMESHIFT; /** * Plugin status events sent from cas system. @@ -261,63 +257,90 @@ public final class MediaCas implements AutoCloseable { * physical CAS modules. */ public static final int PLUGIN_STATUS_PHYSICAL_MODULE_CHANGED = - android.hardware.cas.V1_2.StatusEvent.PLUGIN_PHYSICAL_MODULE_CHANGED; - /** - * The event to indicate that the number of CAS system's session is changed. - */ - public static final int PLUGIN_STATUS_SESSION_NUMBER_CHANGED = - android.hardware.cas.V1_2.StatusEvent.PLUGIN_SESSION_NUMBER_CHANGED; + android.hardware.cas.StatusEvent.PLUGIN_PHYSICAL_MODULE_CHANGED; - private static final Singleton<IMediaCasService> sService = new Singleton<IMediaCasService>() { - @Override - protected IMediaCasService create() { - try { - Log.d(TAG, "Trying to get cas@1.2 service"); - android.hardware.cas.V1_2.IMediaCasService serviceV12 = - android.hardware.cas.V1_2.IMediaCasService.getService(true /*wait*/); - if (serviceV12 != null) { - return serviceV12; + /** The event to indicate that the number of CAS system's session is changed. */ + public static final int PLUGIN_STATUS_SESSION_NUMBER_CHANGED = + android.hardware.cas.StatusEvent.PLUGIN_SESSION_NUMBER_CHANGED; + + private static final Singleton<IMediaCasService> sService = + new Singleton<IMediaCasService>() { + @Override + protected IMediaCasService create() { + try { + Log.d(TAG, "Trying to get AIDL service"); + IMediaCasService serviceAidl = + IMediaCasService.Stub.asInterface( + ServiceManager.getService( + IMediaCasService.DESCRIPTOR + "/default")); + if (serviceAidl != null) { + return serviceAidl; + } + } catch (Exception eAidl) { + Log.d(TAG, "Failed to get cas AIDL service"); + } + return null; } - } catch (Exception eV1_2) { - Log.d(TAG, "Failed to get cas@1.2 service"); - } + }; + + private static final Singleton<android.hardware.cas.V1_0.IMediaCasService> sServiceHidl = + new Singleton<android.hardware.cas.V1_0.IMediaCasService>() { + @Override + protected android.hardware.cas.V1_0.IMediaCasService create() { + try { + Log.d(TAG, "Trying to get cas@1.2 service"); + android.hardware.cas.V1_2.IMediaCasService serviceV12 = + android.hardware.cas.V1_2.IMediaCasService.getService( + true /*wait*/); + if (serviceV12 != null) { + return serviceV12; + } + } catch (Exception eV1_2) { + Log.d(TAG, "Failed to get cas@1.2 service"); + } - try { - Log.d(TAG, "Trying to get cas@1.1 service"); - android.hardware.cas.V1_1.IMediaCasService serviceV11 = - android.hardware.cas.V1_1.IMediaCasService.getService(true /*wait*/); - if (serviceV11 != null) { - return serviceV11; + try { + Log.d(TAG, "Trying to get cas@1.1 service"); + android.hardware.cas.V1_1.IMediaCasService serviceV11 = + android.hardware.cas.V1_1.IMediaCasService.getService( + true /*wait*/); + if (serviceV11 != null) { + return serviceV11; + } + } catch (Exception eV1_1) { + Log.d(TAG, "Failed to get cas@1.1 service"); } - } catch (Exception eV1_1) { - Log.d(TAG, "Failed to get cas@1.1 service"); - } - try { - Log.d(TAG, "Trying to get cas@1.0 service"); - return IMediaCasService.getService(true /*wait*/); - } catch (Exception eV1_0) { - Log.d(TAG, "Failed to get cas@1.0 service"); - } + try { + Log.d(TAG, "Trying to get cas@1.0 service"); + return android.hardware.cas.V1_0.IMediaCasService.getService(true /*wait*/); + } catch (Exception eV1_0) { + Log.d(TAG, "Failed to get cas@1.0 service"); + } - return null; - } - }; + return null; + } + }; static IMediaCasService getService() { return sService.get(); } + static android.hardware.cas.V1_0.IMediaCasService getServiceHidl() { + return sServiceHidl.get(); + } + private void validateInternalStates() { - if (mICas == null) { + if (mICas == null && mICasHidl == null) { throw new IllegalStateException(); } } private void cleanupAndRethrowIllegalState() { mICas = null; - mICasV11 = null; - mICasV12 = null; + mICasHidl = null; + mICasHidl11 = null; + mICasHidl12 = null; throw new IllegalStateException(); } @@ -341,7 +364,7 @@ public final class MediaCas implements AutoCloseable { toBytes((ArrayList<Byte>) msg.obj)); } else if (msg.what == MSG_CAS_SESSION_EVENT) { Bundle bundle = msg.getData(); - ArrayList<Byte> sessionId = toByteArray(bundle.getByteArray(SESSION_KEY)); + byte[] sessionId = bundle.getByteArray(SESSION_KEY); mListener.onSessionEvent(MediaCas.this, createFromSessionId(sessionId), msg.arg1, msg.arg2, bundle.getByteArray(DATA_KEY)); @@ -357,40 +380,94 @@ public final class MediaCas implements AutoCloseable { } } - private final ICasListener.Stub mBinder = new ICasListener.Stub() { - @Override - public void onEvent(int event, int arg, @Nullable ArrayList<Byte> data) - throws RemoteException { - if (mEventHandler != null) { - mEventHandler.sendMessage(mEventHandler.obtainMessage( - EventHandler.MSG_CAS_EVENT, event, arg, data)); - } - } - @Override - public void onSessionEvent(@NonNull ArrayList<Byte> sessionId, - int event, int arg, @Nullable ArrayList<Byte> data) - throws RemoteException { - if (mEventHandler != null) { - Message msg = mEventHandler.obtainMessage(); - msg.what = EventHandler.MSG_CAS_SESSION_EVENT; - msg.arg1 = event; - msg.arg2 = arg; - Bundle bundle = new Bundle(); - bundle.putByteArray(EventHandler.SESSION_KEY, toBytes(sessionId)); - bundle.putByteArray(EventHandler.DATA_KEY, toBytes(data)); - msg.setData(bundle); - mEventHandler.sendMessage(msg); - } - } - @Override - public void onStatusUpdate(byte status, int arg) - throws RemoteException { - if (mEventHandler != null) { - mEventHandler.sendMessage(mEventHandler.obtainMessage( - EventHandler.MSG_CAS_STATUS_EVENT, status, arg)); - } - } - }; + private final ICasListener.Stub mBinder = + new ICasListener.Stub() { + @Override + public void onEvent(int event, int arg, byte[] data) throws RemoteException { + if (mEventHandler != null) { + mEventHandler.sendMessage( + mEventHandler.obtainMessage( + EventHandler.MSG_CAS_EVENT, event, arg, data)); + } + } + + @Override + public void onSessionEvent(byte[] sessionId, int event, int arg, byte[] data) + throws RemoteException { + if (mEventHandler != null) { + Message msg = mEventHandler.obtainMessage(); + msg.what = EventHandler.MSG_CAS_SESSION_EVENT; + msg.arg1 = event; + msg.arg2 = arg; + Bundle bundle = new Bundle(); + bundle.putByteArray(EventHandler.SESSION_KEY, sessionId); + bundle.putByteArray(EventHandler.DATA_KEY, data); + msg.setData(bundle); + mEventHandler.sendMessage(msg); + } + } + + @Override + public void onStatusUpdate(byte status, int arg) throws RemoteException { + if (mEventHandler != null) { + mEventHandler.sendMessage( + mEventHandler.obtainMessage( + EventHandler.MSG_CAS_STATUS_EVENT, status, arg)); + } + } + + @Override + public synchronized String getInterfaceHash() throws android.os.RemoteException { + return ICasListener.Stub.HASH; + } + + @Override + public int getInterfaceVersion() throws android.os.RemoteException { + return ICasListener.Stub.VERSION; + } + }; + + private final android.hardware.cas.V1_2.ICasListener.Stub mBinderHidl = + new android.hardware.cas.V1_2.ICasListener.Stub() { + @Override + public void onEvent(int event, int arg, @Nullable ArrayList<Byte> data) + throws RemoteException { + if (mEventHandler != null) { + mEventHandler.sendMessage( + mEventHandler.obtainMessage( + EventHandler.MSG_CAS_EVENT, event, arg, data)); + } + } + + @Override + public void onSessionEvent( + @NonNull ArrayList<Byte> sessionId, + int event, + int arg, + @Nullable ArrayList<Byte> data) + throws RemoteException { + if (mEventHandler != null) { + Message msg = mEventHandler.obtainMessage(); + msg.what = EventHandler.MSG_CAS_SESSION_EVENT; + msg.arg1 = event; + msg.arg2 = arg; + Bundle bundle = new Bundle(); + bundle.putByteArray(EventHandler.SESSION_KEY, toBytes(sessionId)); + bundle.putByteArray(EventHandler.DATA_KEY, toBytes(data)); + msg.setData(bundle); + mEventHandler.sendMessage(msg); + } + } + + @Override + public void onStatusUpdate(byte status, int arg) throws RemoteException { + if (mEventHandler != null) { + mEventHandler.sendMessage( + mEventHandler.obtainMessage( + EventHandler.MSG_CAS_STATUS_EVENT, status, arg)); + } + } + }; private final TunerResourceManager.ResourcesReclaimListener mResourceListener = new TunerResourceManager.ResourcesReclaimListener() { @@ -422,6 +499,11 @@ public final class MediaCas implements AutoCloseable { mName = null; } + PluginDescriptor(@NonNull AidlCasPluginDescriptor descriptor) { + mCASystemId = descriptor.caSystemId; + mName = descriptor.name; + } + PluginDescriptor(@NonNull HidlCasPluginDescriptor descriptor) { mCASystemId = descriptor.caSystemId; mName = descriptor.name; @@ -467,19 +549,20 @@ public final class MediaCas implements AutoCloseable { } return data; } + /** * Class for an open session with the CA system. */ public final class Session implements AutoCloseable { - final ArrayList<Byte> mSessionId; + final byte[] mSessionId; boolean mIsClosed = false; - Session(@NonNull ArrayList<Byte> sessionId) { - mSessionId = new ArrayList<Byte>(sessionId); + Session(@NonNull byte[] sessionId) { + mSessionId = sessionId; } private void validateSessionInternalStates() { - if (mICas == null) { + if (mICas == null && mICasHidl == null) { throw new IllegalStateException(); } if (mIsClosed) { @@ -496,7 +579,7 @@ public final class MediaCas implements AutoCloseable { */ public boolean equals(Object obj) { if (obj instanceof Session) { - return mSessionId.equals(((Session) obj).mSessionId); + return Arrays.equals(mSessionId, ((Session) obj).mSessionId); } return false; } @@ -515,8 +598,13 @@ public final class MediaCas implements AutoCloseable { validateSessionInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.setSessionPrivateData(mSessionId, toByteArray(data, 0, data.length))); + if (mICas != null) { + mICas.setSessionPrivateData(mSessionId, data); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.setSessionPrivateData( + toByteArray(mSessionId), toByteArray(data, 0, data.length))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -539,8 +627,13 @@ public final class MediaCas implements AutoCloseable { validateSessionInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.processEcm(mSessionId, toByteArray(data, offset, length))); + if (mICas != null) { + mICas.processEcm(mSessionId, data); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.processEcm( + toByteArray(mSessionId), toByteArray(data, offset, length))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -576,15 +669,23 @@ public final class MediaCas implements AutoCloseable { public void sendSessionEvent(int event, int arg, @Nullable byte[] data) throws MediaCasException { validateSessionInternalStates(); + if (mICas != null) { + try { + mICas.sendSessionEvent(mSessionId, event, arg, data); + } catch (RemoteException e) { + cleanupAndRethrowIllegalState(); + } + } - if (mICasV11 == null) { + if (mICasHidl11 == null) { Log.d(TAG, "Send Session Event isn't supported by cas@1.0 interface"); throw new UnsupportedCasException("Send Session Event is not supported"); } try { MediaCasException.throwExceptionIfNeeded( - mICasV11.sendSessionEvent(mSessionId, event, arg, toByteArray(data))); + mICasHidl11.sendSessionEvent( + toByteArray(mSessionId), event, arg, toByteArray(data))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -600,7 +701,7 @@ public final class MediaCas implements AutoCloseable { @NonNull public byte[] getSessionId() { validateSessionInternalStates(); - return toBytes(mSessionId); + return mSessionId; } /** @@ -613,8 +714,12 @@ public final class MediaCas implements AutoCloseable { public void close() { validateSessionInternalStates(); try { - MediaCasStateException.throwExceptionIfNeeded( - mICas.closeSession(mSessionId)); + if (mICas != null) { + mICas.closeSession(mSessionId); + } else { + MediaCasStateException.throwExceptionIfNeeded( + mICasHidl.closeSession(toByteArray(mSessionId))); + } mIsClosed = true; removeSessionFromResourceMap(this); } catch (RemoteException e) { @@ -623,8 +728,8 @@ public final class MediaCas implements AutoCloseable { } } - Session createFromSessionId(@NonNull ArrayList<Byte> sessionId) { - if (sessionId == null || sessionId.size() == 0) { + Session createFromSessionId(byte[] sessionId) { + if (sessionId == null || sessionId.length == 0) { return null; } return new Session(sessionId); @@ -638,12 +743,20 @@ public final class MediaCas implements AutoCloseable { * @return Whether the specified CA system is supported on this device. */ public static boolean isSystemIdSupported(int CA_system_id) { - IMediaCasService service = getService(); - + IMediaCasService service = sService.get(); if (service != null) { try { return service.isSystemIdSupported(CA_system_id); } catch (RemoteException e) { + return false; + } + } + + android.hardware.cas.V1_0.IMediaCasService serviceHidl = sServiceHidl.get(); + if (serviceHidl != null) { + try { + return serviceHidl.isSystemIdSupported(CA_system_id); + } catch (RemoteException e) { } } return false; @@ -655,12 +768,26 @@ public final class MediaCas implements AutoCloseable { * @return an array of descriptors for the available CA plugins. */ public static PluginDescriptor[] enumeratePlugins() { - IMediaCasService service = getService(); - + IMediaCasService service = sService.get(); if (service != null) { try { - ArrayList<HidlCasPluginDescriptor> descriptors = - service.enumeratePlugins(); + AidlCasPluginDescriptor[] descriptors = service.enumeratePlugins(); + if (descriptors.length == 0) { + return null; + } + PluginDescriptor[] results = new PluginDescriptor[descriptors.length]; + for (int i = 0; i < results.length; i++) { + results[i] = new PluginDescriptor(descriptors[i]); + } + return results; + } catch (RemoteException e) { + } + } + + android.hardware.cas.V1_0.IMediaCasService serviceHidl = sServiceHidl.get(); + if (serviceHidl != null) { + try { + ArrayList<HidlCasPluginDescriptor> descriptors = serviceHidl.enumeratePlugins(); if (descriptors.size() == 0) { return null; } @@ -680,29 +807,40 @@ public final class MediaCas implements AutoCloseable { mCasSystemId = casSystemId; mUserId = Process.myUid(); IMediaCasService service = getService(); - android.hardware.cas.V1_2.IMediaCasService serviceV12 = - android.hardware.cas.V1_2.IMediaCasService.castFrom(service); - if (serviceV12 == null) { - android.hardware.cas.V1_1.IMediaCasService serviceV11 = - android.hardware.cas.V1_1.IMediaCasService.castFrom(service); - if (serviceV11 == null) { + if (service != null) { + Log.d(TAG, "Use CAS AIDL interface to create plugin"); + mICas = service.createPlugin(casSystemId, mBinder); + } else { + android.hardware.cas.V1_0.IMediaCasService serviceV10 = getServiceHidl(); + android.hardware.cas.V1_2.IMediaCasService serviceV12 = + android.hardware.cas.V1_2.IMediaCasService.castFrom(serviceV10); + if (serviceV12 == null) { + android.hardware.cas.V1_1.IMediaCasService serviceV11 = + android.hardware.cas.V1_1.IMediaCasService.castFrom(serviceV10); + if (serviceV11 == null) { Log.d(TAG, "Used cas@1_0 interface to create plugin"); - mICas = service.createPlugin(casSystemId, mBinder); - } else { + mICasHidl = serviceV10.createPlugin(casSystemId, mBinderHidl); + } else { Log.d(TAG, "Used cas@1.1 interface to create plugin"); - mICas = mICasV11 = serviceV11.createPluginExt(casSystemId, mBinder); + mICasHidl = + mICasHidl11 = serviceV11.createPluginExt(casSystemId, mBinderHidl); + } + } else { + Log.d(TAG, "Used cas@1.2 interface to create plugin"); + mICasHidl = + mICasHidl11 = + mICasHidl12 = + android.hardware.cas.V1_2.ICas.castFrom( + serviceV12.createPluginExt( + casSystemId, mBinderHidl)); } - } else { - Log.d(TAG, "Used cas@1.2 interface to create plugin"); - mICas = mICasV11 = mICasV12 = - android.hardware.cas.V1_2.ICas - .castFrom(serviceV12.createPluginExt(casSystemId, mBinder)); } } catch(Exception e) { Log.e(TAG, "Failed to create plugin: " + e); mICas = null; + mICasHidl = null; } finally { - if (mICas == null) { + if (mICas == null && mICasHidl == null) { throw new UnsupportedCasException( "Unsupported casSystemId " + casSystemId); } @@ -783,9 +921,22 @@ public final class MediaCas implements AutoCloseable { } IHwBinder getBinder() { + if (mICas != null) { + return null; // Return IHwBinder only for HIDL + } + validateInternalStates(); - return mICas.asBinder(); + return mICasHidl.asBinder(); + } + + /** + * Check if the HAL is an AIDL implementation + * + * @hide + */ + public boolean isAidlHal() { + return mICas != null; } /** @@ -886,8 +1037,12 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.setPrivateData(toByteArray(data, 0, data.length))); + if (mICas != null) { + mICas.setPrivateData(data); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.setPrivateData(toByteArray(data, 0, data.length))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -899,7 +1054,7 @@ public final class MediaCas implements AutoCloseable { @Override public void onValues(int status, ArrayList<Byte> sessionId) { mStatus = status; - mSession = createFromSessionId(sessionId); + mSession = createFromSessionId(toBytes(sessionId)); } } @@ -912,7 +1067,7 @@ public final class MediaCas implements AutoCloseable { @Override public void onValues(int status, ArrayList<Byte> sessionId) { mStatus = status; - mSession = createFromSessionId(sessionId); + mSession = createFromSessionId(toBytes(sessionId)); } } @@ -971,15 +1126,19 @@ public final class MediaCas implements AutoCloseable { int sessionResourceHandle = getSessionResourceHandle(); try { - OpenSessionCallback cb = new OpenSessionCallback(); - mICas.openSession(cb); - MediaCasException.throwExceptionIfNeeded(cb.mStatus); - addSessionToResourceMap(cb.mSession, sessionResourceHandle); - Log.d(TAG, "Write Stats Log for succeed to Open Session."); - FrameworkStatsLog - .write(FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS, mUserId, mCasSystemId, + if (mICasHidl != null) { + OpenSessionCallback cb = new OpenSessionCallback(); + mICasHidl.openSession(cb); + MediaCasException.throwExceptionIfNeeded(cb.mStatus); + addSessionToResourceMap(cb.mSession, sessionResourceHandle); + Log.d(TAG, "Write Stats Log for succeed to Open Session."); + FrameworkStatsLog.write( + FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS, + mUserId, + mCasSystemId, FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS__STATE__SUCCEEDED); - return cb.mSession; + return cb.mSession; + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -1012,14 +1171,30 @@ public final class MediaCas implements AutoCloseable { throws MediaCasException { int sessionResourceHandle = getSessionResourceHandle(); - if (mICasV12 == null) { + if (mICas != null) { + try { + byte[] sessionId = mICas.openSession(sessionUsage, scramblingMode); + Session session = createFromSessionId(sessionId); + addSessionToResourceMap(session, sessionResourceHandle); + Log.d(TAG, "Write Stats Log for succeed to Open Session."); + FrameworkStatsLog.write( + FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS, + mUserId, + mCasSystemId, + FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS__STATE__SUCCEEDED); + return session; + } catch (RemoteException e) { + cleanupAndRethrowIllegalState(); + } + } + if (mICasHidl12 == null) { Log.d(TAG, "Open Session with scrambling mode is only supported by cas@1.2+ interface"); throw new UnsupportedCasException("Open Session with scrambling mode is not supported"); } try { OpenSession_1_2_Callback cb = new OpenSession_1_2_Callback(); - mICasV12.openSession_1_2(sessionUsage, scramblingMode, cb); + mICasHidl12.openSession_1_2(sessionUsage, scramblingMode, cb); MediaCasException.throwExceptionIfNeeded(cb.mStatus); addSessionToResourceMap(cb.mSession, sessionResourceHandle); Log.d(TAG, "Write Stats Log for succeed to Open Session."); @@ -1053,8 +1228,12 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.processEmm(toByteArray(data, offset, length))); + if (mICas != null) { + mICas.processEmm(Arrays.copyOfRange(data, offset, length)); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.processEmm(toByteArray(data, offset, length))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -1092,8 +1271,12 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.sendEvent(event, arg, toByteArray(data))); + if (mICas != null) { + mICas.sendEvent(event, arg, data); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.sendEvent(event, arg, toByteArray(data))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -1114,8 +1297,11 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.provision(provisionString)); + if (mICas != null) { + mICas.provision(provisionString); + } else { + MediaCasException.throwExceptionIfNeeded(mICasHidl.provision(provisionString)); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -1136,8 +1322,12 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.refreshEntitlements(refreshType, toByteArray(refreshData))); + if (mICas != null) { + mICas.refreshEntitlements(refreshType, refreshData); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.refreshEntitlements(refreshType, toByteArray(refreshData))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -1163,6 +1353,13 @@ public final class MediaCas implements AutoCloseable { } finally { mICas = null; } + } else if (mICasHidl != null) { + try { + mICasHidl.release(); + } catch (RemoteException e) { + } finally { + mICasHidl = mICasHidl11 = mICasHidl12 = null; + } } if (mTunerResourceManager != null) { diff --git a/media/java/android/media/MediaDescrambler.java b/media/java/android/media/MediaDescrambler.java index 99bd2549cbc7..b4bdf93db3ab 100644 --- a/media/java/android/media/MediaDescrambler.java +++ b/media/java/android/media/MediaDescrambler.java @@ -17,14 +17,26 @@ package android.media; import android.annotation.NonNull; -import android.hardware.cas.V1_0.*; +import android.hardware.cas.DestinationBuffer; +import android.hardware.cas.IDescrambler; +import android.hardware.cas.ScramblingControl; +import android.hardware.cas.SharedBuffer; +import android.hardware.cas.SubSample; +import android.hardware.cas.V1_0.IDescramblerBase; +import android.hardware.common.Ashmem; +import android.hardware.common.NativeHandle; import android.media.MediaCasException.UnsupportedCasException; import android.os.IHwBinder; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceSpecificException; +import android.os.SharedMemory; +import android.system.ErrnoException; import android.util.Log; +import java.io.IOException; import java.nio.ByteBuffer; +import java.util.ArrayList; /** * MediaDescrambler class can be used in conjunction with {@link android.media.MediaCodec} @@ -39,7 +51,198 @@ import java.nio.ByteBuffer; */ public final class MediaDescrambler implements AutoCloseable { private static final String TAG = "MediaDescrambler"; - private IDescramblerBase mIDescrambler; + private DescramblerWrapper mIDescrambler; + + private interface DescramblerWrapper { + + IHwBinder asBinder(); + + int descramble( + @NonNull ByteBuffer srcBuf, + @NonNull ByteBuffer dstBuf, + @NonNull MediaCodec.CryptoInfo cryptoInfo) + throws RemoteException; + + boolean requiresSecureDecoderComponent(@NonNull String mime) throws RemoteException; + + void setMediaCasSession(byte[] sessionId) throws RemoteException; + + void release() throws RemoteException; + } + ; + + private long getSubsampleInfo( + int numSubSamples, + int[] numBytesOfClearData, + int[] numBytesOfEncryptedData, + SubSample[] subSamples) { + long totalSize = 0; + + for (int i = 0; i < numSubSamples; i++) { + totalSize += numBytesOfClearData[i]; + subSamples[i].numBytesOfClearData = numBytesOfClearData[i]; + totalSize += numBytesOfEncryptedData[i]; + subSamples[i].numBytesOfEncryptedData = numBytesOfEncryptedData[i]; + } + return totalSize; + } + + private ParcelFileDescriptor createSharedMemory(ByteBuffer buffer, String name) + throws RemoteException { + byte[] source = buffer.array(); + if (source.length == 0) { + return null; + } + ParcelFileDescriptor fd = null; + try { + SharedMemory ashmem = SharedMemory.create(name == null ? "" : name, source.length); + ByteBuffer ptr = ashmem.mapReadWrite(); + ptr.put(buffer); + ashmem.unmap(ptr); + fd = ashmem.getFdDup(); + return fd; + } catch (ErrnoException | IOException e) { + throw new RemoteException(e); + } + } + + private class AidlDescrambler implements DescramblerWrapper { + + IDescrambler mAidlDescrambler; + + AidlDescrambler(IDescrambler aidlDescrambler) { + mAidlDescrambler = aidlDescrambler; + } + + @Override + public IHwBinder asBinder() { + return null; + } + + @Override + public int descramble( + @NonNull ByteBuffer src, + @NonNull ByteBuffer dst, + @NonNull MediaCodec.CryptoInfo cryptoInfo) + throws RemoteException { + SubSample[] subSamples = new SubSample[cryptoInfo.numSubSamples]; + long totalLength = + getSubsampleInfo( + cryptoInfo.numSubSamples, + cryptoInfo.numBytesOfClearData, + cryptoInfo.numBytesOfEncryptedData, + subSamples); + SharedBuffer srcBuffer = new SharedBuffer(); + DestinationBuffer dstBuffer; + srcBuffer.heapBase = new Ashmem(); + srcBuffer.heapBase.fd = createSharedMemory(src, "Descrambler Source Buffer"); + srcBuffer.heapBase.size = src.array().length; + if (dst == null) { + dstBuffer = DestinationBuffer.nonsecureMemory(srcBuffer); + } else { + ParcelFileDescriptor pfd = + createSharedMemory(dst, "Descrambler Destination Buffer"); + NativeHandle nh = new NativeHandle(); + nh.fds = new ParcelFileDescriptor[] {pfd}; + nh.ints = new int[] {1}; // Mark 1 since source buffer also uses it? + dstBuffer = DestinationBuffer.secureMemory(nh); + } + @ScramblingControl int control = cryptoInfo.key[0]; + + return mAidlDescrambler.descramble( + (byte) control, + subSamples, + srcBuffer, + src.position(), + dstBuffer, + dst.position()); + } + + @Override + public boolean requiresSecureDecoderComponent(@NonNull String mime) throws RemoteException { + return mAidlDescrambler.requiresSecureDecoderComponent(mime); + } + + @Override + public void setMediaCasSession(byte[] sessionId) throws RemoteException { + mAidlDescrambler.setMediaCasSession(sessionId); + } + + @Override + public void release() throws RemoteException { + mAidlDescrambler.release(); + } + } + + private class HidlDescrambler implements DescramblerWrapper { + + IDescramblerBase mHidlDescrambler; + + HidlDescrambler(IDescramblerBase hidlDescrambler) { + mHidlDescrambler = hidlDescrambler; + native_setup(hidlDescrambler.asBinder()); + } + + @Override + public IHwBinder asBinder() { + return mHidlDescrambler.asBinder(); + } + + @Override + public int descramble( + @NonNull ByteBuffer srcBuf, + @NonNull ByteBuffer dstBuf, + @NonNull MediaCodec.CryptoInfo cryptoInfo) + throws RemoteException { + + try { + return native_descramble( + cryptoInfo.key[0], + cryptoInfo.key[1], + cryptoInfo.numSubSamples, + cryptoInfo.numBytesOfClearData, + cryptoInfo.numBytesOfEncryptedData, + srcBuf, + srcBuf.position(), + srcBuf.limit(), + dstBuf, + dstBuf.position(), + dstBuf.limit()); + } catch (ServiceSpecificException e) { + MediaCasStateException.throwExceptionIfNeeded(e.errorCode, e.getMessage()); + } catch (RemoteException e) { + cleanupAndRethrowIllegalState(); + } + return -1; + } + + @Override + public boolean requiresSecureDecoderComponent(@NonNull String mime) throws RemoteException { + return mHidlDescrambler.requiresSecureDecoderComponent(mime); + } + + @Override + public void setMediaCasSession(byte[] sessionId) throws RemoteException { + ArrayList<Byte> byteArray = new ArrayList<>(); + + if (sessionId != null) { + int length = sessionId.length; + byteArray = new ArrayList<Byte>(length); + for (int i = 0; i < length; i++) { + byteArray.add(Byte.valueOf(sessionId[i])); + } + } + + MediaCasStateException.throwExceptionIfNeeded( + mHidlDescrambler.setMediaCasSession(byteArray)); + } + + @Override + public void release() throws RemoteException { + mHidlDescrambler.release(); + native_release(); + } + } private final void validateInternalStates() { if (mIDescrambler == null) { @@ -61,7 +264,14 @@ public final class MediaDescrambler implements AutoCloseable { */ public MediaDescrambler(int CA_system_id) throws UnsupportedCasException { try { - mIDescrambler = MediaCas.getService().createDescrambler(CA_system_id); + if (MediaCas.getService() != null) { + mIDescrambler = + new AidlDescrambler(MediaCas.getService().createDescrambler(CA_system_id)); + } else if (MediaCas.getServiceHidl() != null) { + mIDescrambler = + new HidlDescrambler( + MediaCas.getServiceHidl().createDescrambler(CA_system_id)); + } } catch(Exception e) { Log.e(TAG, "Failed to create descrambler: " + e); mIDescrambler = null; @@ -70,7 +280,6 @@ public final class MediaDescrambler implements AutoCloseable { throw new UnsupportedCasException("Unsupported CA_system_id " + CA_system_id); } } - native_setup(mIDescrambler.asBinder()); } IHwBinder getBinder() { @@ -117,8 +326,7 @@ public final class MediaDescrambler implements AutoCloseable { validateInternalStates(); try { - MediaCasStateException.throwExceptionIfNeeded( - mIDescrambler.setMediaCasSession(session.mSessionId)); + mIDescrambler.setMediaCasSession(session.mSessionId); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -126,27 +334,31 @@ public final class MediaDescrambler implements AutoCloseable { /** * Scramble control value indicating that the samples are not scrambled. + * * @see #descramble(ByteBuffer, ByteBuffer, android.media.MediaCodec.CryptoInfo) */ - public static final byte SCRAMBLE_CONTROL_UNSCRAMBLED = 0; + public static final byte SCRAMBLE_CONTROL_UNSCRAMBLED = (byte) ScramblingControl.UNSCRAMBLED; /** * Scramble control value reserved and shouldn't be used currently. + * * @see #descramble(ByteBuffer, ByteBuffer, android.media.MediaCodec.CryptoInfo) */ - public static final byte SCRAMBLE_CONTROL_RESERVED = 1; + public static final byte SCRAMBLE_CONTROL_RESERVED = (byte) ScramblingControl.RESERVED; /** * Scramble control value indicating that the even key is used. + * * @see #descramble(ByteBuffer, ByteBuffer, android.media.MediaCodec.CryptoInfo) */ - public static final byte SCRAMBLE_CONTROL_EVEN_KEY = 2; + public static final byte SCRAMBLE_CONTROL_EVEN_KEY = (byte) ScramblingControl.EVENKEY; /** * Scramble control value indicating that the odd key is used. + * * @see #descramble(ByteBuffer, ByteBuffer, android.media.MediaCodec.CryptoInfo) */ - public static final byte SCRAMBLE_CONTROL_ODD_KEY = 3; + public static final byte SCRAMBLE_CONTROL_ODD_KEY = (byte) ScramblingControl.ODDKEY; /** * Scramble flag for a hint indicating that the descrambling request is for @@ -207,14 +419,7 @@ public final class MediaDescrambler implements AutoCloseable { } try { - return native_descramble( - cryptoInfo.key[0], - cryptoInfo.key[1], - cryptoInfo.numSubSamples, - cryptoInfo.numBytesOfClearData, - cryptoInfo.numBytesOfEncryptedData, - srcBuf, srcBuf.position(), srcBuf.limit(), - dstBuf, dstBuf.position(), dstBuf.limit()); + return mIDescrambler.descramble(srcBuf, dstBuf, cryptoInfo); } catch (ServiceSpecificException e) { MediaCasStateException.throwExceptionIfNeeded(e.errorCode, e.getMessage()); } catch (RemoteException e) { @@ -233,7 +438,6 @@ public final class MediaDescrambler implements AutoCloseable { mIDescrambler = null; } } - native_release(); } @Override @@ -256,4 +460,4 @@ public final class MediaDescrambler implements AutoCloseable { } private long mNativeContext; -}
\ No newline at end of file +} diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java index dab188e40c1f..b11a81047bf8 100644 --- a/media/java/android/media/MediaExtractor.java +++ b/media/java/android/media/MediaExtractor.java @@ -36,7 +36,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -325,14 +324,6 @@ public final class MediaExtractor { } } - private ArrayList<Byte> toByteArray(@NonNull byte[] data) { - ArrayList<Byte> byteArray = new ArrayList<Byte>(data.length); - for (int i = 0; i < data.length; i++) { - byteArray.add(i, Byte.valueOf(data[i])); - } - return byteArray; - } - /** * Retrieves the information about the conditional access system used to scramble * a track. @@ -357,7 +348,7 @@ public final class MediaExtractor { buf.rewind(); final byte[] sessionId = new byte[buf.remaining()]; buf.get(sessionId); - session = mMediaCas.createFromSessionId(toByteArray(sessionId)); + session = mMediaCas.createFromSessionId(sessionId); } return new CasInfo(systemId, session, privateData); } diff --git a/opengl/java/android/opengl/Matrix.java b/opengl/java/android/opengl/Matrix.java index 88896c35a616..ce3f57ebfea1 100644 --- a/opengl/java/android/opengl/Matrix.java +++ b/opengl/java/android/opengl/Matrix.java @@ -16,8 +16,6 @@ package android.opengl; -import androidx.annotation.NonNull; - /** * Matrix math utilities. These methods operate on OpenGL ES format * matrices and vectors stored in float arrays. @@ -40,11 +38,7 @@ import androidx.annotation.NonNull; public class Matrix { /** Temporary memory for operations that need temporary matrix data. */ - private static final ThreadLocal<float[]> ThreadTmp = new ThreadLocal() { - @Override protected float[] initialValue() { - return new float[32]; - } - }; + private final static float[] sTemp = new float[32]; /** * @deprecated All methods are static, do not instantiate this class. @@ -52,40 +46,6 @@ public class Matrix { @Deprecated public Matrix() {} - private static boolean overlap( - float[] a, int aStart, int aLength, float[] b, int bStart, int bLength) { - if (a != b) { - return false; - } - - if (aStart == bStart) { - return true; - } - - int aEnd = aStart + aLength; - int bEnd = bStart + bLength; - - if (aEnd == bEnd) { - return true; - } - - if (aStart < bStart && bStart < aEnd) { - return true; - } - if (aStart < bEnd && bEnd < aEnd) { - return true; - } - - if (bStart < aStart && aStart < bEnd) { - return true; - } - if (bStart < aEnd && aEnd < bEnd) { - return true; - } - - return false; - } - /** * Multiplies two 4x4 matrices together and stores the result in a third 4x4 * matrix. In matrix notation: result = lhs x rhs. Due to the way @@ -93,9 +53,9 @@ public class Matrix { * effect as first multiplying by the rhs matrix, then multiplying by * the lhs matrix. This is the opposite of what you might expect. * <p> - * The same float array may be passed for result, lhs, and/or rhs. This - * operation is expected to do the correct thing if the result elements - * overlap with either of the lhs or rhs elements. + * The same float array may be passed for result, lhs, and/or rhs. However, + * the result element values are undefined if the result elements overlap + * either the lhs or rhs elements. * * @param result The float array that holds the result. * @param resultOffset The offset into the result array where the result is @@ -105,101 +65,20 @@ public class Matrix { * @param rhs The float array that holds the right-hand-side matrix. * @param rhsOffset The offset into the rhs array where the rhs is stored. * - * @throws IllegalArgumentException under any of the following conditions: - * result, lhs, or rhs are null; - * resultOffset + 16 > result.length - * or lhsOffset + 16 > lhs.length - * or rhsOffset + 16 > rhs.length; - * resultOffset < 0 or lhsOffset < 0 or rhsOffset < 0 + * @throws IllegalArgumentException if result, lhs, or rhs are null, or if + * resultOffset + 16 > result.length or lhsOffset + 16 > lhs.length or + * rhsOffset + 16 > rhs.length. */ - public static void multiplyMM(float[] result, int resultOffset, - float[] lhs, int lhsOffset, float[] rhs, int rhsOffset) { - // error checking - if (result == null) { - throw new IllegalArgumentException("result == null"); - } - if (lhs == null) { - throw new IllegalArgumentException("lhs == null"); - } - if (rhs == null) { - throw new IllegalArgumentException("rhs == null"); - } - if (resultOffset < 0) { - throw new IllegalArgumentException("resultOffset < 0"); - } - if (lhsOffset < 0) { - throw new IllegalArgumentException("lhsOffset < 0"); - } - if (rhsOffset < 0) { - throw new IllegalArgumentException("rhsOffset < 0"); - } - if (result.length < resultOffset + 16) { - throw new IllegalArgumentException("result.length < resultOffset + 16"); - } - if (lhs.length < lhsOffset + 16) { - throw new IllegalArgumentException("lhs.length < lhsOffset + 16"); - } - if (rhs.length < rhsOffset + 16) { - throw new IllegalArgumentException("rhs.length < rhsOffset + 16"); - } - - // Check for overlap between rhs and result or lhs and result - if ( overlap(result, resultOffset, 16, lhs, lhsOffset, 16) - || overlap(result, resultOffset, 16, rhs, rhsOffset, 16) ) { - float[] tmp = ThreadTmp.get(); - for (int i=0; i<4; i++) { - final float rhs_i0 = rhs[ 4*i + 0 + rhsOffset ]; - float ri0 = lhs[ 0 + lhsOffset ] * rhs_i0; - float ri1 = lhs[ 1 + lhsOffset ] * rhs_i0; - float ri2 = lhs[ 2 + lhsOffset ] * rhs_i0; - float ri3 = lhs[ 3 + 16 ] * rhs_i0; - for (int j=1; j<4; j++) { - final float rhs_ij = rhs[ 4*i + j + rhsOffset]; - ri0 += lhs[ 4*j + 0 + lhsOffset ] * rhs_ij; - ri1 += lhs[ 4*j + 1 + lhsOffset ] * rhs_ij; - ri2 += lhs[ 4*j + 2 + lhsOffset ] * rhs_ij; - ri3 += lhs[ 4*j + 3 + lhsOffset ] * rhs_ij; - } - tmp[ 4*i + 0 ] = ri0; - tmp[ 4*i + 1 ] = ri1; - tmp[ 4*i + 2 ] = ri2; - tmp[ 4*i + 3 ] = ri3; - } - - // copy from tmp to result - for (int i=0; i < 16; i++) { - result[ i + resultOffset ] = tmp[ i ]; - } - - } else { - for (int i=0; i<4; i++) { - final float rhs_i0 = rhs[ 4*i + 0 + rhsOffset ]; - float ri0 = lhs[ 0 + lhsOffset ] * rhs_i0; - float ri1 = lhs[ 1 + lhsOffset ] * rhs_i0; - float ri2 = lhs[ 2 + lhsOffset ] * rhs_i0; - float ri3 = lhs[ 3 + lhsOffset ] * rhs_i0; - for (int j=1; j<4; j++) { - final float rhs_ij = rhs[ 4*i + j + rhsOffset]; - ri0 += lhs[ 4*j + 0 + lhsOffset ] * rhs_ij; - ri1 += lhs[ 4*j + 1 + lhsOffset ] * rhs_ij; - ri2 += lhs[ 4*j + 2 + lhsOffset ] * rhs_ij; - ri3 += lhs[ 4*j + 3 + lhsOffset ] * rhs_ij; - } - result[ 4*i + 0 + resultOffset ] = ri0; - result[ 4*i + 1 + resultOffset ] = ri1; - result[ 4*i + 2 + resultOffset ] = ri2; - result[ 4*i + 3 + resultOffset ] = ri3; - } - } - } + public static native void multiplyMM(float[] result, int resultOffset, + float[] lhs, int lhsOffset, float[] rhs, int rhsOffset); /** * Multiplies a 4 element vector by a 4x4 matrix and stores the result in a * 4-element column vector. In matrix notation: result = lhs x rhs * <p> * The same float array may be passed for resultVec, lhsMat, and/or rhsVec. - * This operation is expected to do the correct thing if the result elements - * overlap with either of the lhs or rhs elements. + * However, the resultVec element values are undefined if the resultVec + * elements overlap either the lhsMat or rhsVec elements. * * @param resultVec The float array that holds the result vector. * @param resultVecOffset The offset into the result array where the result @@ -210,67 +89,14 @@ public class Matrix { * @param rhsVecOffset The offset into the rhs vector where the rhs vector * is stored. * - * @throws IllegalArgumentException under any of the following conditions: - * resultVec, lhsMat, or rhsVec are null; - * resultVecOffset + 4 > resultVec.length - * or lhsMatOffset + 16 > lhsMat.length - * or rhsVecOffset + 4 > rhsVec.length; - * resultVecOffset < 0 or lhsMatOffset < 0 or rhsVecOffset < 0 + * @throws IllegalArgumentException if resultVec, lhsMat, + * or rhsVec are null, or if resultVecOffset + 4 > resultVec.length + * or lhsMatOffset + 16 > lhsMat.length or + * rhsVecOffset + 4 > rhsVec.length. */ - public static void multiplyMV(float[] resultVec, + public static native void multiplyMV(float[] resultVec, int resultVecOffset, float[] lhsMat, int lhsMatOffset, - float[] rhsVec, int rhsVecOffset) { - // error checking - if (resultVec == null) { - throw new IllegalArgumentException("resultVec == null"); - } - if (lhsMat == null) { - throw new IllegalArgumentException("lhsMat == null"); - } - if (rhsVec == null) { - throw new IllegalArgumentException("rhsVec == null"); - } - if (resultVecOffset < 0) { - throw new IllegalArgumentException("resultVecOffset < 0"); - } - if (lhsMatOffset < 0) { - throw new IllegalArgumentException("lhsMatOffset < 0"); - } - if (rhsVecOffset < 0) { - throw new IllegalArgumentException("rhsVecOffset < 0"); - } - if (resultVec.length < resultVecOffset + 4) { - throw new IllegalArgumentException("resultVec.length < resultVecOffset + 4"); - } - if (lhsMat.length < lhsMatOffset + 16) { - throw new IllegalArgumentException("lhsMat.length < lhsMatOffset + 16"); - } - if (rhsVec.length < rhsVecOffset + 4) { - throw new IllegalArgumentException("rhsVec.length < rhsVecOffset + 4"); - } - - float tmp0 = lhsMat[0 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + - lhsMat[0 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + - lhsMat[0 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + - lhsMat[0 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; - float tmp1 = lhsMat[1 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + - lhsMat[1 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + - lhsMat[1 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + - lhsMat[1 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; - float tmp2 = lhsMat[2 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + - lhsMat[2 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + - lhsMat[2 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + - lhsMat[2 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; - float tmp3 = lhsMat[3 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + - lhsMat[3 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + - lhsMat[3 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + - lhsMat[3 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; - - resultVec[ 0 + resultVecOffset ] = tmp0; - resultVec[ 1 + resultVecOffset ] = tmp1; - resultVec[ 2 + resultVecOffset ] = tmp2; - resultVec[ 3 + resultVecOffset ] = tmp3; - } + float[] rhsVec, int rhsVecOffset); /** * Transposes a 4 x 4 matrix. @@ -711,9 +537,10 @@ public class Matrix { public static void rotateM(float[] rm, int rmOffset, float[] m, int mOffset, float a, float x, float y, float z) { - float[] tmp = ThreadTmp.get(); - setRotateM(tmp, 16, a, x, y, z); - multiplyMM(rm, rmOffset, m, mOffset, tmp, 16); + synchronized(sTemp) { + setRotateM(sTemp, 0, a, x, y, z); + multiplyMM(rm, rmOffset, m, mOffset, sTemp, 0); + } } /** @@ -729,7 +556,11 @@ public class Matrix { */ public static void rotateM(float[] m, int mOffset, float a, float x, float y, float z) { - rotateM(m, mOffset, m, mOffset, a, x, y, z); + synchronized(sTemp) { + setRotateM(sTemp, 0, a, x, y, z); + multiplyMM(sTemp, 16, m, mOffset, sTemp, 0); + System.arraycopy(sTemp, 16, m, mOffset, 16); + } } /** @@ -809,14 +640,9 @@ public class Matrix { * @param rm returns the result * @param rmOffset index into rm where the result matrix starts * @param x angle of rotation, in degrees - * @param y is broken, do not use + * @param y angle of rotation, in degrees * @param z angle of rotation, in degrees - * - * @deprecated This method is incorrect around the y axis. This method is - * deprecated and replaced (below) by setRotateEulerM2 which - * behaves correctly */ - @Deprecated public static void setRotateEulerM(float[] rm, int rmOffset, float x, float y, float z) { x *= (float) (Math.PI / 180.0f); @@ -853,64 +679,6 @@ public class Matrix { } /** - * Converts Euler angles to a rotation matrix. - * - * @param rm returns the result - * @param rmOffset index into rm where the result matrix starts - * @param x angle of rotation, in degrees - * @param y angle of rotation, in degrees - * @param z angle of rotation, in degrees - * - * @throws IllegalArgumentException if rm is null; - * or if rmOffset + 16 > rm.length; - * rmOffset < 0 - */ - public static void setRotateEulerM2(@NonNull float[] rm, int rmOffset, - float x, float y, float z) { - if (rm == null) { - throw new IllegalArgumentException("rm == null"); - } - if (rmOffset < 0) { - throw new IllegalArgumentException("rmOffset < 0"); - } - if (rm.length < rmOffset + 16) { - throw new IllegalArgumentException("rm.length < rmOffset + 16"); - } - - x *= (float) (Math.PI / 180.0f); - y *= (float) (Math.PI / 180.0f); - z *= (float) (Math.PI / 180.0f); - float cx = (float) Math.cos(x); - float sx = (float) Math.sin(x); - float cy = (float) Math.cos(y); - float sy = (float) Math.sin(y); - float cz = (float) Math.cos(z); - float sz = (float) Math.sin(z); - float cxsy = cx * sy; - float sxsy = sx * sy; - - rm[rmOffset + 0] = cy * cz; - rm[rmOffset + 1] = -cy * sz; - rm[rmOffset + 2] = sy; - rm[rmOffset + 3] = 0.0f; - - rm[rmOffset + 4] = sxsy * cz + cx * sz; - rm[rmOffset + 5] = -sxsy * sz + cx * cz; - rm[rmOffset + 6] = -sx * cy; - rm[rmOffset + 7] = 0.0f; - - rm[rmOffset + 8] = -cxsy * cz + sx * sz; - rm[rmOffset + 9] = cxsy * sz + sx * cz; - rm[rmOffset + 10] = cx * cy; - rm[rmOffset + 11] = 0.0f; - - rm[rmOffset + 12] = 0.0f; - rm[rmOffset + 13] = 0.0f; - rm[rmOffset + 14] = 0.0f; - rm[rmOffset + 15] = 1.0f; - } - - /** * Defines a viewing transformation in terms of an eye point, a center of * view, and an up vector. * diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java index 76025ab7aa7d..0446165be5fc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java @@ -53,7 +53,9 @@ public class ImageTransformState extends TransformState { return true; } if (otherState instanceof ImageTransformState) { - return mIcon != null && mIcon.sameAs(((ImageTransformState) otherState).getIcon()); + final Icon otherIcon = ((ImageTransformState) otherState).mIcon; + return mIcon == otherIcon || (mIcon != null && otherIcon != null && mIcon.sameAs( + otherIcon)); } return false; } diff --git a/services/core/Android.bp b/services/core/Android.bp index 9268fc03bd2f..bf71e6b8ee6d 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -154,8 +154,8 @@ java_library_static { "android.hardware.health-translate-java", "android.hardware.light-V1-java", "android.hardware.tv.cec-V1.1-java", - "android.hardware.tv.cec-V1-java", - "android.hardware.tv.hdmi-V1-java", + "android.hardware.tv.hdmi.cec-V1-java", + "android.hardware.tv.hdmi.connection-V1-java", "android.hardware.weaver-V1.0-java", "android.hardware.biometrics.face-V1.0-java", "android.hardware.biometrics.fingerprint-V2.3-java", diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java index bf0052d31826..dbba9eea15b1 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecController.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java @@ -19,16 +19,16 @@ package com.android.server.hdmi; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.hdmi.HdmiPortInfo; -import android.hardware.tv.cec.CecMessage; -import android.hardware.tv.cec.IHdmiCec; -import android.hardware.tv.cec.IHdmiCecCallback; import android.hardware.tv.cec.V1_0.HotplugEvent; import android.hardware.tv.cec.V1_0.IHdmiCec.getPhysicalAddressCallback; import android.hardware.tv.cec.V1_0.OptionKey; import android.hardware.tv.cec.V1_0.Result; import android.hardware.tv.cec.V1_0.SendMessageResult; -import android.hardware.tv.hdmi.IHdmi; -import android.hardware.tv.hdmi.IHdmiCallback; +import android.hardware.tv.hdmi.cec.CecMessage; +import android.hardware.tv.hdmi.cec.IHdmiCec; +import android.hardware.tv.hdmi.cec.IHdmiCecCallback; +import android.hardware.tv.hdmi.connection.IHdmiConnection; +import android.hardware.tv.hdmi.connection.IHdmiConnectionCallback; import android.icu.util.IllformedLocaleException; import android.icu.util.ULocale; import android.os.Binder; @@ -178,7 +178,7 @@ final class HdmiCecController { if (controller != null) { return controller; } - HdmiLogger.warning("Unable to use CEC and HDMI AIDL HALs"); + HdmiLogger.warning("Unable to use CEC and HDMI Connection AIDL HALs"); controller = createWithNativeWrapper(service, new NativeWrapperImpl11(), atomWriter); if (controller != null) { @@ -872,14 +872,14 @@ final class HdmiCecController { private static final class NativeWrapperImplAidl implements NativeWrapper, IBinder.DeathRecipient { private IHdmiCec mHdmiCec; - private IHdmi mHdmi; + private IHdmiConnection mHdmiConnection; @Nullable private HdmiCecCallback mCallback; private final Object mLock = new Object(); @Override public String nativeInit() { - return connectToHal() ? mHdmiCec.toString() + " " + mHdmi.toString() : null; + return connectToHal() ? mHdmiCec.toString() + " " + mHdmiConnection.toString() : null; } boolean connectToHal() { @@ -896,15 +896,15 @@ final class HdmiCecController { HdmiLogger.error("Couldn't link to death : ", e); } - mHdmi = - IHdmi.Stub.asInterface( - ServiceManager.getService(IHdmi.DESCRIPTOR + "/default")); - if (mHdmi == null) { - HdmiLogger.error("Could not initialize HDMI AIDL HAL"); + mHdmiConnection = + IHdmiConnection.Stub.asInterface( + ServiceManager.getService(IHdmiConnection.DESCRIPTOR + "/default")); + if (mHdmiConnection == null) { + HdmiLogger.error("Could not initialize HDMI Connection AIDL HAL"); return false; } try { - mHdmi.asBinder().linkToDeath(this, 0); + mHdmiConnection.asBinder().linkToDeath(this, 0); } catch (RemoteException e) { HdmiLogger.error("Couldn't link to death : ", e); } @@ -915,8 +915,8 @@ final class HdmiCecController { public void binderDied() { // One of the services died, try to reconnect to both. mHdmiCec.asBinder().unlinkToDeath(this, 0); - mHdmi.asBinder().unlinkToDeath(this, 0); - HdmiLogger.error("HDMI or CEC service died, reconnecting"); + mHdmiConnection.asBinder().unlinkToDeath(this, 0); + HdmiLogger.error("HDMI Connection or CEC service died, reconnecting"); connectToHal(); // Reconnect the callback if (mCallback != null) { @@ -935,7 +935,7 @@ final class HdmiCecController { } try { // Create an AIDL callback that can callback onHotplugEvent - mHdmi.setCallback(new HdmiCallbackAidl(callback)); + mHdmiConnection.setCallback(new HdmiConnectionCallbackAidl(callback)); } catch (RemoteException e) { HdmiLogger.error("Couldn't initialise tv.hdmi callback : ", e); } @@ -1052,10 +1052,11 @@ final class HdmiCecController { @Override public HdmiPortInfo[] nativeGetPortInfos() { try { - android.hardware.tv.hdmi.HdmiPortInfo[] hdmiPortInfos = mHdmi.getPortInfo(); + android.hardware.tv.hdmi.connection.HdmiPortInfo[] hdmiPortInfos = + mHdmiConnection.getPortInfo(); HdmiPortInfo[] hdmiPortInfo = new HdmiPortInfo[hdmiPortInfos.length]; int i = 0; - for (android.hardware.tv.hdmi.HdmiPortInfo portInfo : hdmiPortInfos) { + for (android.hardware.tv.hdmi.connection.HdmiPortInfo portInfo : hdmiPortInfos) { hdmiPortInfo[i] = new HdmiPortInfo( portInfo.portId, @@ -1076,7 +1077,7 @@ final class HdmiCecController { @Override public boolean nativeIsConnected(int port) { try { - return mHdmi.isConnected(port); + return mHdmiConnection.isConnected(port); } catch (RemoteException e) { HdmiLogger.error("Failed to get connection info : ", e); return false; @@ -1580,10 +1581,10 @@ final class HdmiCecController { } } - private static final class HdmiCallbackAidl extends IHdmiCallback.Stub { + private static final class HdmiConnectionCallbackAidl extends IHdmiConnectionCallback.Stub { private final HdmiCecCallback mHdmiCecCallback; - HdmiCallbackAidl(HdmiCecCallback hdmiCecCallback) { + HdmiConnectionCallbackAidl(HdmiCecCallback hdmiCecCallback) { mHdmiCecCallback = hdmiCecCallback; } @@ -1594,12 +1595,12 @@ final class HdmiCecController { @Override public synchronized String getInterfaceHash() throws android.os.RemoteException { - return IHdmiCallback.Stub.HASH; + return IHdmiConnectionCallback.Stub.HASH; } @Override public int getInterfaceVersion() throws android.os.RemoteException { - return IHdmiCallback.Stub.VERSION; + return IHdmiConnectionCallback.Stub.VERSION; } } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index ed4ba0d0eacd..7f8f40626c56 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -3202,8 +3202,7 @@ public final class PowerManagerService extends SystemService } final PowerGroup powerGroup = mPowerGroups.get(groupId); wakefulness = powerGroup.getWakefulnessLocked(); - if ((wakefulness == WAKEFULNESS_DREAMING || wakefulness == WAKEFULNESS_DOZING) && - powerGroup.isSandmanSummonedLocked() && powerGroup.isReadyLocked()) { + if (powerGroup.isSandmanSummonedLocked() && powerGroup.isReadyLocked()) { startDreaming = canDreamLocked(powerGroup) || canDozeLocked(powerGroup); powerGroup.setSandmanSummonedLocked(/* isSandmanSummoned= */ false); } else { |