1 /* 2 * Copyright (C) 2021 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.sensorprivacy.cts.usemiccamera 18 19 import android.app.Activity 20 import android.app.AppOpsManager 21 import android.content.BroadcastReceiver 22 import android.content.Context 23 import android.content.Intent 24 import android.content.IntentFilter 25 import android.hardware.camera2.CameraCaptureSession 26 import android.hardware.camera2.CameraCharacteristics 27 import android.hardware.camera2.CameraDevice 28 import android.hardware.camera2.CameraManager 29 import android.hardware.camera2.params.OutputConfiguration 30 import android.hardware.camera2.params.SessionConfiguration 31 import android.media.AudioFormat 32 import android.media.AudioRecord 33 import android.media.ImageReader 34 import android.media.MediaRecorder 35 import android.os.Bundle 36 import android.os.Handler 37 import android.os.Process 38 import android.util.Size 39 40 private const val MIC = 1 shl 0 41 private const val CAM = 1 shl 1 42 43 private const val SAMPLING_RATE = 8000 44 45 class UseMicCamera : Activity() { 46 private var audioRecord: AudioRecord? = null 47 private var cameraDevice: CameraDevice? = null 48 private lateinit var appOpsManager: AppOpsManager 49 50 companion object { 51 const val MIC_CAM_ACTIVITY_ACTION = 52 "android.sensorprivacy.cts.usemiccamera.action.USE_MIC_CAM" 53 const val FINISH_MIC_CAM_ACTIVITY_ACTION = 54 "android.sensorprivacy.cts.usemiccamera.action.FINISH_USE_MIC_CAM" 55 const val USE_MIC_EXTRA = 56 "android.sensorprivacy.cts.usemiccamera.extra.USE_MICROPHONE" 57 const val USE_CAM_EXTRA = 58 "android.sensorprivacy.cts.usemiccamera.extra.USE_CAMERA" 59 const val DELAYED_ACTIVITY_EXTRA = 60 "android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY" 61 const val DELAYED_ACTIVITY_NEW_TASK_EXTRA = 62 "android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY_NEW_TASK" 63 } 64 onCreatenull65 override fun onCreate(savedInstanceState: Bundle?) { 66 super.onCreate(savedInstanceState) 67 68 val handler = Handler(mainLooper) 69 appOpsManager = applicationContext.getSystemService(AppOpsManager::class.java)!! 70 71 registerReceiver(object : BroadcastReceiver() { 72 override fun onReceive(context: Context?, intent: Intent?) { 73 unregisterReceiver(this) 74 audioRecord?.stop() 75 cameraDevice?.close() 76 appOpsManager.finishOp(AppOpsManager.OPSTR_CAMERA, 77 Process.myUid(), applicationContext.packageName) 78 finishAndRemoveTask() 79 } 80 }, IntentFilter(FINISH_MIC_CAM_ACTIVITY_ACTION)) 81 82 val useMic = intent.getBooleanExtra(USE_MIC_EXTRA, false) 83 val useCam = intent.getBooleanExtra(USE_CAM_EXTRA, false) 84 if (useMic) { 85 handler.postDelayed({ openMic() }, 1000) 86 } 87 if (useCam) { 88 handler.postDelayed({ openCam() }, 1000) 89 } 90 91 if (intent.getBooleanExtra(DELAYED_ACTIVITY_EXTRA, false)) { 92 handler.postDelayed({ 93 val intent = Intent(this, BlankActivity::class.java) 94 if (intent.getBooleanExtra(DELAYED_ACTIVITY_NEW_TASK_EXTRA, false)) { 95 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 96 } 97 startActivity(intent) 98 }, 2000) 99 } 100 } 101 openMicnull102 private fun openMic() { 103 audioRecord = AudioRecord.Builder() 104 .setAudioFormat(AudioFormat.Builder() 105 .setSampleRate(SAMPLING_RATE) 106 .setEncoding(AudioFormat.ENCODING_PCM_16BIT) 107 .setChannelMask(AudioFormat.CHANNEL_IN_MONO).build()) 108 .setAudioSource(MediaRecorder.AudioSource.DEFAULT) 109 .setBufferSizeInBytes( 110 AudioRecord.getMinBufferSize(SAMPLING_RATE, 111 AudioFormat.CHANNEL_IN_MONO, 112 AudioFormat.ENCODING_PCM_16BIT) * 10) 113 .build() 114 115 audioRecord?.startRecording() 116 } 117 openCamnull118 private fun openCam() { 119 val cameraManager = getSystemService(CameraManager::class.java)!! 120 121 val cameraId = cameraManager!!.cameraIdList[0] 122 val config = cameraManager!!.getCameraCharacteristics(cameraId) 123 .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) 124 val outputFormat = config!!.outputFormats[0] 125 val outputSize: Size = config!!.getOutputSizes(outputFormat)[0] 126 val handler = Handler(mainLooper) 127 128 val cameraDeviceCallback = object : CameraDevice.StateCallback() { 129 override fun onOpened(cD: CameraDevice) { 130 val imageReader = ImageReader.newInstance( 131 outputSize.width, outputSize.height, outputFormat, 2) 132 133 val builder = cD.createCaptureRequest(CameraDevice.TEMPLATE_RECORD) 134 builder.addTarget(imageReader.surface) 135 val captureRequest = builder.build() 136 val sessionConfiguration = SessionConfiguration( 137 SessionConfiguration.SESSION_REGULAR, 138 listOf(OutputConfiguration(imageReader.surface)), 139 mainExecutor, 140 object : CameraCaptureSession.StateCallback() { 141 override fun onConfigured(session: CameraCaptureSession) { 142 session.capture(captureRequest, null, handler) 143 appOpsManager.startOpNoThrow(AppOpsManager.OPSTR_CAMERA, 144 Process.myUid(), applicationContext.packageName) 145 } 146 147 override fun onConfigureFailed(session: CameraCaptureSession) {} 148 }) 149 150 cD.createCaptureSession(sessionConfiguration) 151 cameraDevice = cD 152 } 153 154 override fun onDisconnected(cameraDevice: CameraDevice) { 155 } 156 override fun onError(cameraDevice: CameraDevice, i: Int) { 157 } 158 } 159 160 cameraManager!!.openCamera(cameraId, mainExecutor, cameraDeviceCallback) 161 } 162 }