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 }