1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.security.cts.camera.open 18 19 import android.app.Service 20 import android.content.Intent 21 import android.graphics.SurfaceTexture 22 import android.opengl.EGL14 23 import android.opengl.EGLConfig 24 import android.opengl.EGLContext 25 import android.opengl.EGLDisplay 26 import android.opengl.EGLSurface 27 import android.opengl.GLES11Ext 28 import android.opengl.GLES30 29 import android.os.IBinder 30 import android.security.cts.camera.open.lib.IntentKeys 31 import android.util.Log 32 import android.view.Surface 33 import java.nio.IntBuffer 34 import java.util.concurrent.Executors 35 36 class CameraOpenerService : Service() { 37 38 private lateinit var keys: IntentKeys 39 private lateinit var cameraOpener: CameraOpener 40 41 private lateinit var display: EGLDisplay 42 private lateinit var config: EGLConfig 43 private lateinit var context: EGLContext 44 private lateinit var placeholderSurface: EGLSurface 45 46 private var cameraTexId: Int = -1 47 private var cameraSurface: Surface? = null 48 private var cameraSurfaceTexture: SurfaceTexture? = null 49 50 private val renderExecutor = Executors.newSingleThreadExecutor() 51 onCreatenull52 override fun onCreate() { 53 Log.v(TAG, "onCreate") 54 super.onCreate() 55 keys = IntentKeys(packageName) 56 57 display = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY) 58 checkEglError("eglGetDisplay") 59 60 val version = intArrayOf(0, 0) 61 if (!EGL14.eglInitialize(display, version, 0, version, 1)) { 62 throw RuntimeException("Unable to initialize EGL14") 63 } 64 checkEglError("eglInitialize") 65 66 val rgbaBits = 8 67 val configAttribList = 68 intArrayOf( 69 EGL14.EGL_RENDERABLE_TYPE, 70 EGL14.EGL_OPENGL_ES2_BIT, 71 EGL14.EGL_SURFACE_TYPE, 72 EGL14.EGL_PBUFFER_BIT or EGL14.EGL_WINDOW_BIT, 73 EGL14.EGL_RED_SIZE, 74 rgbaBits, 75 EGL14.EGL_GREEN_SIZE, 76 rgbaBits, 77 EGL14.EGL_BLUE_SIZE, 78 rgbaBits, 79 EGL14.EGL_ALPHA_SIZE, 80 rgbaBits, 81 EGL14.EGL_DEPTH_SIZE, 82 16, 83 EGL14.EGL_NONE, 84 ) 85 86 val configs = arrayOfNulls<EGLConfig>(1) 87 val numConfigs = intArrayOf(1) 88 EGL14.eglChooseConfig(display, configAttribList, 0, configs, 0, configs.size, numConfigs, 0) 89 config = configs[0]!! 90 91 val requestedVersion = 2 92 val contextAttribList = 93 intArrayOf(EGL14.EGL_CONTEXT_CLIENT_VERSION, requestedVersion, EGL14.EGL_NONE) 94 95 context = EGL14.eglCreateContext(display, config, EGL14.EGL_NO_CONTEXT, contextAttribList, 0) 96 if (context == EGL14.EGL_NO_CONTEXT) { 97 throw RuntimeException("Failed to create EGL context") 98 } 99 100 val placeholderSurfaceAttribs = 101 intArrayOf(EGL14.EGL_WIDTH, 1, EGL14.EGL_HEIGHT, 1, EGL14.EGL_NONE) 102 placeholderSurface = 103 EGL14.eglCreatePbufferSurface(display, config, placeholderSurfaceAttribs, /*offset*/ 0) 104 105 EGL14.eglMakeCurrent(display, placeholderSurface, placeholderSurface, context) 106 107 cameraTexId = createTexture() 108 cameraSurfaceTexture = SurfaceTexture(cameraTexId) 109 cameraSurface = Surface(cameraSurfaceTexture) 110 111 cameraOpener = 112 CameraOpener( 113 context = this, keys, textureView = null, surfaceTexture = cameraSurfaceTexture) 114 } 115 onDestroynull116 override fun onDestroy() { 117 Log.v(TAG, "onDestroy") 118 super.onDestroy() 119 cameraOpener.release() 120 121 EGL14.eglMakeCurrent(display, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT) 122 EGL14.eglDestroySurface(display, placeholderSurface) 123 placeholderSurface = EGL14.EGL_NO_SURFACE 124 EGL14.eglDestroyContext(display, context) 125 context = EGL14.EGL_NO_CONTEXT 126 EGL14.eglReleaseThread() 127 EGL14.eglTerminate(display) 128 display = EGL14.EGL_NO_DISPLAY 129 } 130 onBindnull131 override fun onBind(intent: Intent): IBinder { 132 Log.v(TAG, "onBind") 133 return cameraOpener.aidlInterface 134 } 135 checkEglErrornull136 private fun checkEglError(op: String) { 137 val eglError = EGL14.eglGetError() 138 if (eglError != EGL14.EGL_SUCCESS) { 139 val msg = op + ": eglError 0x" + Integer.toHexString(eglError) 140 throw IllegalStateException(msg) 141 } 142 } 143 checkGlErrornull144 private fun checkGlError(op: String) { 145 val error = GLES30.glGetError() 146 if (error != GLES30.GL_NO_ERROR) { 147 val msg = op + ": glError " + glErrorStr(error) 148 throw IllegalStateException(msg) 149 } 150 } 151 glErrorStrnull152 private fun glErrorStr(error: Int) = 153 when (error) { 154 GLES30.GL_INVALID_ENUM -> "GL_INVALID_ENUM" 155 GLES30.GL_INVALID_VALUE -> "GL_INVALID_VALUE" 156 GLES30.GL_INVALID_OPERATION -> "GL_INVALID_OPERATION" 157 GLES30.GL_OUT_OF_MEMORY -> "GL_OUT_OF_MEMORY" 158 else -> "0x" + Integer.toHexString(error) 159 } 160 createTexturenull161 private fun createTexture(): Int { 162 val buffer = IntBuffer.allocate(1) 163 GLES30.glGenTextures(1, buffer) 164 checkGlError("glGenTextures") 165 val texId = buffer.get(0) 166 val target = GLES11Ext.GL_TEXTURE_EXTERNAL_OES 167 GLES30.glBindTexture(target, /* texture= */ texId) 168 checkGlError("glBindTexture") 169 170 GLES30.glTexParameteri(target, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR) 171 GLES30.glTexParameteri(target, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR) 172 GLES30.glTexParameteri(target, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE) 173 GLES30.glTexParameteri(target, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE) 174 return texId 175 } 176 177 private companion object { 178 private val TAG = CameraOpenerService::class.java.simpleName 179 } 180 } 181