From c2be31c4263670a76eabfd24d8a80f20111958df Mon Sep 17 00:00:00 2001 From: Girish Suragani Date: Fri, 8 Sep 2023 12:54:25 +0530 Subject: [PATCH] Added latest alfred changes from super app repo (#9) --- .../main/java/com/navi/alfred/AlfredConfig.kt | 54 +- .../java/com/navi/alfred/AlfredManager.kt | 813 ++++++++---------- .../java/com/navi/alfred/db/AlfredDatabase.kt | 14 +- .../navi/alfred/db/AlfredDatabaseHelper.kt | 4 +- .../java/com/navi/alfred/db/dao/AlfredDao.kt | 30 +- .../com/navi/alfred/db/model/AlfredEntity.kt | 18 +- .../deserializer/AnalyticsDataDeserializer.kt | 13 +- .../deserializer/MetricsDataDeserializer.kt | 13 +- .../deserializer/SessionDataDeserializer.kt | 13 +- .../alfred/dispatcher/AlfredDispatcher.kt | 11 +- .../com/navi/alfred/model/ErrorMessage.kt | 15 +- .../navi/alfred/model/EventMetricRequest.kt | 9 +- .../com/navi/alfred/model/SessionRequest.kt | 42 +- .../alfred/network/AlfredNetworkRepository.kt | 28 +- .../alfred/network/AlfredRetrofitProvider.kt | 101 ++- .../alfred/network/AlfredRetrofitService.kt | 2 +- .../alfred/network/model/CruiseResponse.kt | 21 +- .../com/navi/alfred/utils/AlfredConstants.kt | 13 +- .../com/navi/alfred/utils/ApiConstants.kt | 9 +- .../main/java/com/navi/alfred/utils/Ext.kt | 12 +- .../com/navi/alfred/utils/NetworkUtils.kt | 26 +- .../alfred/utils/ScreenShotStorageHelper.kt | 2 +- .../main/java/com/navi/alfred/utils/Utils.kt | 215 +++-- .../com/navi/alfred/worker/AddEventTask.kt | 9 +- .../com/navi/alfred/worker/AddMetricTask.kt | 14 +- .../com/navi/alfred/worker/AnalyticsTask.kt | 5 +- .../alfred/worker/AnalyticsTaskProcessor.kt | 5 +- .../navi/alfred/worker/UploadFileWorker.kt | 87 +- 28 files changed, 834 insertions(+), 764 deletions(-) diff --git a/navi-alfred/src/main/java/com/navi/alfred/AlfredConfig.kt b/navi-alfred/src/main/java/com/navi/alfred/AlfredConfig.kt index 35c62bf..3a9a548 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/AlfredConfig.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/AlfredConfig.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2022-2023 by Navi Technologies Limited + * * Copyright © 2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -12,7 +12,9 @@ import android.provider.Settings import android.text.TextUtils import com.navi.alfred.utils.AlfredConstants import com.navi.alfred.utils.getCarrierName +import com.navi.alfred.utils.getNetworkType import java.util.* + data class AlfredConfig( private var appVersionCode: String = "", private var appVersionName: String = "", @@ -40,23 +42,22 @@ data class AlfredConfig( private var cpuEnableStatus: Boolean = false, private var memoryEnableStatus: Boolean = false, private var metricsApiEnableStatus: Boolean = false, - private var apiResponseEnableStatus:Boolean=false, - private var apiRequestEnableStatus:Boolean=false, - private var enabledApiPath: List? = null, var batteryPercentageBeforeEventStart: Float? = null, private var disableScreenList: List? = null, + private var maskingEnabledScreenList: List? = null, private var disableModuleList: List? = null, private var snapshotPerSecond: Int = 1, private var enableAlfred: Boolean = false, private var disableDialogScreenShot: Boolean = false, private var zipFileName: String? = null, private var disableAlfredLogs: Boolean = true - ) { - fun getDeviceId(): String = Settings.System.getString( - AlfredManager.applicationContext.contentResolver, Settings.Secure.ANDROID_ID - ) + fun getDeviceId(): String = + Settings.System.getString( + AlfredManager.applicationContext.contentResolver, + Settings.Secure.ANDROID_ID + ) fun setEventStartRecordingTime(setToNext: Boolean? = false) { if (setToNext == true) { @@ -133,7 +134,7 @@ data class AlfredConfig( fun getNetworkCarrier(): String? = getCarrierName(AlfredManager.applicationContext) - fun getNetworkType(): String = com.navi.alfred.utils.getNetworkType(AlfredManager.applicationContext) + fun getNetworkType(): String = getNetworkType(AlfredManager.applicationContext) fun getBatteryPercentage(): Float = com.navi.alfred.utils.getBatteryPercentage(AlfredManager.applicationContext) @@ -173,12 +174,15 @@ data class AlfredConfig( this.batteryPercentageBeforeEventStart = getBatteryPercentage() } - fun getCpuUsage(): Float = getCpuUsage() + fun getCpuUsage(): Float = com.navi.alfred.utils.getCpuUsage() - fun getMemoryUsage(): Float = getMemoryUsage() + fun getMemoryUsage(): Float = com.navi.alfred.utils.getMemoryUsage() fun getStorageUsage(): Float { - val (totalSize, freeSize) = com.navi.alfred.utils.getStorageUsage(context = AlfredManager.applicationContext) + val (totalSize, freeSize) = + com.navi.alfred.utils.getStorageUsage( + context = AlfredManager.applicationContext + ) return (totalSize - freeSize).toFloat() } @@ -186,6 +190,10 @@ data class AlfredConfig( this.disableScreenList = disableScreenList } + fun setMaskingEnabledScreenList(maskingEnabledScreenList: List) { + this.maskingEnabledScreenList = maskingEnabledScreenList + } + fun setDisableModuleList(disableModuleList: List) { this.disableModuleList = disableModuleList } @@ -212,6 +220,8 @@ data class AlfredConfig( fun getDisableScreenList(): List? = this.disableScreenList + fun getMaskingEnabledScreenList(): List? = this.maskingEnabledScreenList + fun setCpuEnableStatus(status: Boolean) { this.cpuEnableStatus = status } @@ -227,25 +237,11 @@ data class AlfredConfig( fun setApiMetricsEnableStatus(status: Boolean) { this.metricsApiEnableStatus = status } + fun getMetricsApiEnableStatus(): Boolean = this.metricsApiEnableStatus - fun setApiResponseEnableStatus(status: Boolean) { - this.apiResponseEnableStatus = status - } - fun getApiResponseEnableStatus(): Boolean = this.apiResponseEnableStatus - - fun setApiRequestEnableStatus(status: Boolean) { - this.apiRequestEnableStatus = status - } - fun getApiRequestEnableStatus(): Boolean = this.apiRequestEnableStatus - - fun setEnabledApiPath(enabledApiPath: List?) { - this.enabledApiPath = enabledApiPath - } - fun getEnabledApiPath():Set? = this.enabledApiPath?.toSet() - - fun setDisableDialogScreenShot(status: Boolean){ - this.disableDialogScreenShot=status + fun setDisableDialogScreenShot(status: Boolean) { + this.disableDialogScreenShot = status } fun getDisableDialogScreenShot(): Boolean { diff --git a/navi-alfred/src/main/java/com/navi/alfred/AlfredManager.kt b/navi-alfred/src/main/java/com/navi/alfred/AlfredManager.kt index ab8e383..1c6393f 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/AlfredManager.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/AlfredManager.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2022-2023 by Navi Technologies Limited + * * Copyright © 2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -11,7 +11,6 @@ import android.app.Dialog import android.content.Context import android.graphics.Bitmap import android.graphics.Canvas -import android.util.Log import android.view.KeyEvent.ACTION_DOWN import android.view.KeyEvent.ACTION_UP import android.view.MotionEvent @@ -45,12 +44,10 @@ import com.navi.alfred.network.AlfredNetworkRepository import com.navi.alfred.network.AlfredRetrofitProvider import com.navi.alfred.network.model.CruiseResponse import com.navi.alfred.utils.AlfredConstants -import com.navi.alfred.utils.AlfredConstants.ALFRED import com.navi.alfred.utils.AlfredConstants.API_METRICS import com.navi.alfred.utils.AlfredConstants.CODE_API_BAD_REQUEST import com.navi.alfred.utils.AlfredConstants.CODE_API_SUCCESS import com.navi.alfred.utils.AlfredConstants.THIRD_PARTY_MODULE -import com.navi.alfred.utils.AlfredConstants.X_TARGET import com.navi.alfred.utils.AlfredConstants.ZIP_FILE_EXTENSION import com.navi.alfred.utils.ScreenShotStorageHelper import com.navi.alfred.utils.captureScreen @@ -75,17 +72,18 @@ import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.Response import java.io.File import java.lang.reflect.Type -import java.util.* +import java.util.Timer +import java.util.TimerTask +import java.util.UUID import java.util.concurrent.Executors import kotlin.concurrent.fixedRateTimer - object AlfredManager { lateinit var config: AlfredConfig lateinit var applicationContext: Context private var previousTouchEvent: NaviMotionEvent = NaviMotionEvent() - val mutex = Mutex() + private val mutex = Mutex() private val coroutineDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() private val repository = AlfredNetworkRepository() private val completableJob = Job() @@ -97,6 +95,7 @@ object AlfredManager { private const val imageThreshHoldValue: Int = 60 private const val imageSecondThreshHoldValue: Int = 100 private var screenShotCaptureDelay: Long = 1000L + private var isAppInBackground: Boolean = false private var hasRecordingStarted: Boolean = false var dialog: Dialog? = null private var timer: Timer? = null @@ -104,22 +103,23 @@ object AlfredManager { private var viewLayoutDelay: Long = 1000 private var currentScreenName: String? = null private var currentModuleName: String? = null + private var sessionIdForCrash: String? = null + private var sessionStartRecordingTimeForCrash: Long? = null + private var eventStartRecordingTimeForCrash: Long? = null val workFailureData: MutableList = mutableListOf() - private var retryCount: Int = 0 private lateinit var zipFileDetails: List - private val exceptionHandler = CoroutineExceptionHandler { _, _ -> - } + private val exceptionHandler = CoroutineExceptionHandler { _, _ -> } private val coroutineScope = CoroutineScope(Dispatchers.IO + completableJob + exceptionHandler) fun init(config: AlfredConfig, context: Context) { - AlfredManager.config = config - applicationContext = context + this.config = config + this.applicationContext = context AlfredRetrofitProvider.init(applicationContext) startSyncEvents(context) alfredDataBase = AlfredDatabaseHelper.getAnalyticsDatabase(applicationContext) - screenShotDao = alfredDataBase.screenShotDao() - zipDetailsDao = alfredDataBase.zipDetailsDao() - apiMetricDao = alfredDataBase.apiMetricDao() + this.screenShotDao = alfredDataBase.screenShotDao() + this.zipDetailsDao = alfredDataBase.zipDetailsDao() + this.apiMetricDao = alfredDataBase.apiMetricDao() } fun startRecording( @@ -139,67 +139,71 @@ object AlfredManager { config.setEventStartRecordingTime() handleDeviceAttributes() } - currentScreenName = screenName + setCurrentScreenName(screenName) currentModuleName = moduleName hasRecordingStarted = true screenShotTimer?.cancel() screenShotTimer = Timer() var bmpForCanvas: Pair? = null var bmpForThirdPartySdkScreen: Bitmap? = null - val timerTask: TimerTask = object : TimerTask() { - override fun run() { - coroutineScope.launch(Dispatchers.IO) { - if (moduleName == THIRD_PARTY_MODULE) { - if (bmpForThirdPartySdkScreen == null) { - bmpForThirdPartySdkScreen = - thirdPartyScreenView?.let { captureScreenshotOfCustomView(it) } - } - insertScreenShotPathInDb( - this, applicationContext, bmpForThirdPartySdkScreen - ) - } else { - if (bmpForCanvas == null) { - delay(viewLayoutDelay) - bmpForCanvas = createBitmapForView(view) - } - try { - if (dialog != null) { - captureBottomSheet( - view, - context, - screenName, - bmpForCanvas?.first, - rootBmp = bmpForCanvas?.second, - moduleName = moduleName - ) - } else { - captureScreen( - view, - context, - screenName = screenName, - scope = coroutineScope, - canvas = bmpForCanvas?.first, - bmp = bmpForCanvas?.second, - moduleName = moduleName - ) + val timerTask: TimerTask = + object : TimerTask() { + override fun run() { + coroutineScope.launch(Dispatchers.IO) { + if (moduleName == THIRD_PARTY_MODULE) { + if (bmpForThirdPartySdkScreen == null) { + bmpForThirdPartySdkScreen = + thirdPartyScreenView?.let { captureScreenshotOfCustomView(it) } + } + insertScreenShotPathInDb( + this, + applicationContext, + bmpForThirdPartySdkScreen + ) + } else { + if (bmpForCanvas == null) { + delay(viewLayoutDelay) + bmpForCanvas = createBitmapForView(view) + } + try { + if (dialog != null) { + captureBottomSheet( + view, + context, + currentScreenName, + bmpForCanvas?.first, + rootBmp = bmpForCanvas?.second, + moduleName = moduleName + ) + } else { + captureScreen( + view, + context, + screenName = currentScreenName, + scope = coroutineScope, + canvas = bmpForCanvas?.first, + bmp = bmpForCanvas?.second, + moduleName = moduleName + ) + } + } catch (e: Exception) { + e.log() } - } catch (e: Exception) { - e.log() } + handleScreenShot() } - handleScreenShot() } } - } screenShotCaptureDelay = (1000 / config.getSnapshotPerSecond().toLong()) screenShotTimer?.schedule(timerTask, 0, screenShotCaptureDelay) } private suspend fun handleScreenShot() { - if (ScreenShotStorageHelper.images.size == imageThreshHoldValue || ScreenShotStorageHelper.images.size == imageSecondThreshHoldValue) { - toZip( - screenShotDao.fetchScreenShotsPath(imageThreshHoldValue) - ) + if ( + ScreenShotStorageHelper.images.size == imageThreshHoldValue || + ScreenShotStorageHelper.images.size == imageSecondThreshHoldValue + ) { + toZip(screenShotDao.fetchScreenShotsPath(imageThreshHoldValue)) } else { if (ScreenShotStorageHelper.images.size == 1) { checkToStartZipUpload() @@ -210,10 +214,7 @@ object AlfredManager { private suspend fun checkToStartZipUpload() { val zipFileName = config.getZipFileName().toString() if (zipFileName.isNotEmpty()) { - if (checkFileExists( - zipFileName, applicationContext - ) != null - ) { + if (checkFileExists(zipFileName, applicationContext) != null) { if (!hasUploadFlowStarted) { hasUploadFlowStarted = true getPreSignedUrl(zipFileName) @@ -230,22 +231,23 @@ object AlfredManager { rootBmp: Bitmap? = null, moduleName: String? = null ) { - if(config.getDisableDialogScreenShot()){ + if (config.getDisableDialogScreenShot()) { return } val bottomSheetView = dialog?.window?.decorView?.rootView if (bottomSheetView != null) { val bottomSheetCanvasForBitmap = createBitmapForView(bottomSheetView) - val bottomSheetScreenShot = captureScreen( - bottomSheetView, - context, - true, - screenName, - coroutineScope, - bottomSheetCanvasForBitmap?.first, - bottomSheetCanvasForBitmap?.second, - moduleName = moduleName - ) + val bottomSheetScreenShot = + captureScreen( + bottomSheetView, + context, + true, + screenName, + coroutineScope, + bottomSheetCanvasForBitmap?.first, + bottomSheetCanvasForBitmap?.second, + moduleName = moduleName + ) val backgroundScreenShot = captureScreen( view, @@ -278,7 +280,8 @@ object AlfredManager { if (zipDetailsDao.getZipFilesDetailsCount() > 0) { zipFileDetails = zipDetailsDao.fetchAllZipFilesDetails() zipFileDetails.forEachIndexed { index, DumpZipDetailsHelper -> - if (checkFileExists( + if ( + checkFileExists( fileName = DumpZipDetailsHelper.zipFileName, applicationContext ) != null @@ -295,27 +298,23 @@ object AlfredManager { fun measureInflatedView(view: View) { view.layoutParams = ViewGroup.LayoutParams(1080, 1920) view.measure( - View.MeasureSpec.makeMeasureSpec( - view.layoutParams.width, View.MeasureSpec.EXACTLY - ), View.MeasureSpec.makeMeasureSpec( - view.layoutParams.height, View.MeasureSpec.EXACTLY - ) + View.MeasureSpec.makeMeasureSpec(view.layoutParams.width, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(view.layoutParams.height, View.MeasureSpec.EXACTLY) ) view.layout(0, 0, view.measuredWidth, view.measuredHeight) } suspend fun getCruiseConfig() { - val response = repository.cruiseConfig( - AlfredConstants.DEFAULT_CRUISE_CONFIG_URL, - config.getAppVersionName(), - config.getOsVersion(), - config.getDeviceId() - ) + val response = + repository.cruiseConfig( + AlfredConstants.DEFAULT_CRUISE_CONFIG_URL, + config.getAppVersionName(), + config.getOsVersion(), + config.getDeviceId() + ) if (response.isSuccessful && response.code() == CODE_API_SUCCESS) { try { - response.body()?.let { cruiseResponse -> - setCruiseConfig(cruiseResponse) - } + response.body()?.let { cruiseResponse -> setCruiseConfig(cruiseResponse) } } catch (e: Exception) { e.log() } @@ -327,9 +326,7 @@ object AlfredManager { if (responseList.isNotEmpty()) { val cruiseConfig = responseList.first() cruiseConfig.source.let { source -> - source.enable?.let { sourceConfig -> - config.setAlfredStatus(sourceConfig) - } + source.enable?.let { sourceConfig -> config.setAlfredStatus(sourceConfig) } source.recordingsConfig?.let { recordingConfig -> recordingConfig.enable?.let { enable -> config.setEnableRecordingStatus(enable) @@ -346,6 +343,9 @@ object AlfredManager { recordingConfig.disableScreens?.let { disableScreen -> config.setDisableScreenList(disableScreen) } + recordingConfig.maskingEnabledScreens?.let { maskingEnabledScreens -> + config.setMaskingEnabledScreenList(maskingEnabledScreens) + } recordingConfig.disableModules?.let { disableModuleList -> config.setDisableModuleList(disableModuleList) } @@ -363,15 +363,6 @@ object AlfredManager { metricsConfig.disableApiPerformance?.let { api_monitor_status -> config.setApiMetricsEnableStatus(!api_monitor_status) } - metricsConfig.disableApiRequest?.let { api_request_status -> - config.setApiRequestEnableStatus(!api_request_status) - } - metricsConfig.disableApiResponse?.let { api_response_status -> - config.setApiResponseEnableStatus(!api_response_status) - } - metricsConfig.enabledApiPaths.let {enabled_api_path -> - config.setEnabledApiPath(enabled_api_path) - } } } } @@ -382,129 +373,118 @@ object AlfredManager { zipFileName: String, dumpFlow: Boolean = false, index: Int? = null, - workManagerFlow: Boolean? = false, - alfredSessionId: String? = null, - eventStartRecordingTime: Long? = null, - sessionStartRecordingTime: Long? = null + workManagerFlow: Boolean? = false ) { - mutex.withLock { - config.setAlfredEventId() - val bucketKey = config.getAlfredEventId().plus(ZIP_FILE_EXTENSION) - val response = repository.getPreSignedUrl(bucketKey) - if (response.isSuccessful && response.code() == CODE_API_SUCCESS) { - if (workManagerFlow == true) { - retryCount = 0 + config.setAlfredEventId() + val bucketKey = config.getAlfredEventId().plus(ZIP_FILE_EXTENSION) + val response = repository.getPreSignedUrl(bucketKey) + if (response.isSuccessful && response.code() == CODE_API_SUCCESS) { + checkFileExists(zipFileName, applicationContext)?.let { file -> + response.body()?.data?.let { + uploadFile( + file, + it, + dumpFlow, + index, + zipFileName, + workManagerFlow = workManagerFlow + ) } - checkFileExists( - zipFileName, applicationContext - )?.let { file -> - response.body()?.data?.let { url -> - uploadFile( - file, - url, - dumpFlow, - index, - zipFileName, - workManagerFlow = workManagerFlow, - alfredSessionId = alfredSessionId, - eventStartRecordingTime = eventStartRecordingTime, - sessionStartRecordingTime = sessionStartRecordingTime - ) - } - } - } else { - if (!dumpFlow) { - hasUploadFlowStarted = false - config.getEventStartRecordingTime()?.let { eventStartRecordingTime -> - insertZipDetailsToDbForDumpingLater( - config.getAlfredSessionId(), - config.getSessionStartRecordingTime(), - eventStartRecordingTime, - zipFileName - ) - } - config.setEventStartRecordingTime(true) - } - if (workManagerFlow == true) { - uploadWorkManagerFailedZip(zipFileName) - } else { + } + } else { + if (!dumpFlow) { + hasUploadFlowStarted = false + config.getEventStartRecordingTime()?.let { eventStartRecordingTime -> + insertZipDetailsToDbForDumpingLater( + config.getAlfredSessionId(), + config.getSessionStartRecordingTime(), + eventStartRecordingTime, + zipFileName + ) } + config.setEventStartRecordingTime(true) + } + if (workManagerFlow == true) { + uploadWorkManagerFailedZip() } } } - private fun uploadWorkManagerFailedZip(zipFileName: String) { - retryCount +=1 + private fun uploadWorkManagerFailedZip() { if (workFailureData.size > 0) { val inputData = workFailureData[0] WorkManager.getInstance(applicationContext).cancelWorkById(inputData.id) - if (retryCount <= 3) { - val requestData = Data.Builder() + val requestData = + Data.Builder() .putString(AlfredConstants.ALFRED_SESSION_ID, inputData.alfredSessionId) .putLong( AlfredConstants.SESSION_START_RECORDING_TIME, inputData.sessionStartRecordingTime - ).putLong( + ) + .putLong( AlfredConstants.EVENT_START_RECORDING_TIME, inputData.eventStartRecordingTime - ).putString( + ) + .putString( AlfredConstants.SCREENSHOT_LIST, Gson().toJson(inputData.screenShots) ) .build() - buildWorkManager(requestData) - } else { - insertZipDetailsToDbForDumpingLater( - inputData.alfredSessionId.toString(), - inputData.sessionStartRecordingTime, - inputData.eventStartRecordingTime, - zipFileName - ) - } + buildWorkManager(requestData) workFailureData.removeAt(0) } - } + } private fun checkAndInitiateFileUploadWorkManager() { val screenShotList = screenShotDao.fetchAllScreenShotsPath() screenShotDao.deleteAllScreenShot() ScreenShotStorageHelper.clearAll() + isAppInBackground = false hasRecordingStarted = false config.clearZipFileName() - val requestData = Data.Builder() - .putString(AlfredConstants.ALFRED_SESSION_ID, config.getAlfredSessionId()) - .putLong( - AlfredConstants.SESSION_START_RECORDING_TIME, - config.getSessionStartRecordingTime() - ).putLong( - AlfredConstants.EVENT_START_RECORDING_TIME, - config.getEventStartRecordingTime() ?: 0L - ).putString(AlfredConstants.SCREENSHOT_LIST, Gson().toJson(screenShotList)) - .build() + val requestData = + Data.Builder() + .putString(AlfredConstants.ALFRED_SESSION_ID, config.getAlfredSessionId()) + .putLong( + AlfredConstants.SESSION_START_RECORDING_TIME, + config.getSessionStartRecordingTime() + ) + .putLong( + AlfredConstants.EVENT_START_RECORDING_TIME, + config.getEventStartRecordingTime() ?: 0L + ) + .putString(AlfredConstants.SCREENSHOT_LIST, Gson().toJson(screenShotList)) + .build() buildWorkManager(requestData) } private fun buildWorkManager(requestData: Data) { - val constraints = Constraints.Builder().setRequiresBatteryNotLow(false) - .setRequiredNetworkType(NetworkType.CONNECTED).build() - val uniqueWorkName = "YOUR_UNIQUE_WORK_NAME" - val uniqueWorkStatus = WorkManager.getInstance(applicationContext) - .getWorkInfosForUniqueWork(uniqueWorkName).get() - if (uniqueWorkStatus.isNullOrEmpty()) { - val uniqueWorkRequest = OneTimeWorkRequestBuilder() - .setConstraints(constraints) - .setInputData(requestData) + val constraints = + Constraints.Builder() + .setRequiresBatteryNotLow(false) + .setRequiredNetworkType(NetworkType.CONNECTED) .build() + val uniqueWorkName = "YOUR_UNIQUE_WORK_NAME" + val uniqueWorkStatus = + WorkManager.getInstance(applicationContext) + .getWorkInfosForUniqueWork(uniqueWorkName) + .get() + if (uniqueWorkStatus.isNullOrEmpty()) { + val uniqueWorkRequest = + OneTimeWorkRequestBuilder() + .setConstraints(constraints) + .setInputData(requestData) + .build() WorkManager.getInstance(applicationContext) .beginUniqueWork(uniqueWorkName, ExistingWorkPolicy.KEEP, uniqueWorkRequest) .enqueue() } else { - val workRequest = OneTimeWorkRequestBuilder() - .setConstraints(constraints) - .setInputData(requestData) - .build() - WorkManager.getInstance(applicationContext) - .enqueue(workRequest) + val workRequest = + OneTimeWorkRequestBuilder() + .setConstraints(constraints) + .setInputData(requestData) + .build() + WorkManager.getInstance(applicationContext).enqueue(workRequest) } } @@ -514,26 +494,13 @@ object AlfredManager { dumpFlow: Boolean = false, index: Int? = null, zipFileName: String, - workManagerFlow: Boolean? = false, - alfredSessionId: String? = null, - eventStartRecordingTime: Long? = null, - sessionStartRecordingTime: Long? = null + workManagerFlow: Boolean? = false ) { val requestBody = uploadFile.asRequestBody("application/zip".toMediaTypeOrNull()) - val uploadResponse = repository.uploadZipToS3( - url, requestBody - ) + val uploadResponse = repository.uploadZipToS3(url, requestBody) if (uploadResponse.isSuccessful && uploadResponse.code() == CODE_API_SUCCESS) { uploadFile.delete() - if (workManagerFlow == true) { - retryCount = 0 - } - sendAlfredSessionEvent( - dumpFlow, index, - alfredSessionId = alfredSessionId, - eventStartRecordingTime = eventStartRecordingTime, - sessionStartRecordingTime = sessionStartRecordingTime - ) + sendAlfredSessionEvent(dumpFlow, index) } else { if (!dumpFlow) { config.getEventStartRecordingTime()?.let { eventStartRecordingTime -> @@ -547,7 +514,7 @@ object AlfredManager { config.setEventStartRecordingTime(true) } if (workManagerFlow == true) { - uploadWorkManagerFailedZip(zipFileName) + uploadWorkManagerFailedZip() } } if (!dumpFlow) { @@ -562,21 +529,39 @@ object AlfredManager { zipFileName: String ) { zipDetailsDao.insert( - data = ZipDetailsHelper( - alfredSessionId = alfredSessionId, - sessionStartRecordingTime = sessionStartRecordingTime, - eventStartRecordingTime = eventStartRecordingTime, - zipFileName = zipFileName - ) + data = + ZipDetailsHelper( + alfredSessionId = alfredSessionId, + sessionStartRecordingTime = sessionStartRecordingTime, + eventStartRecordingTime = eventStartRecordingTime, + zipFileName = zipFileName + ) ) } - private fun deleteScreenShot(imagePathList: List) { + private fun deleteScreenShot() { try { - clearScreenShot(imagePathList) - val idList = imagePathList.map { it.id } - screenShotDao.deleteScreenShot(idList) - ScreenShotStorageHelper.deleteKItems(idList.size) + val screenShotPathList: List = + if (screenShotDao.getScreenShotCount() >= imageThreshHoldValue) { + screenShotDao.fetchScreenShotsPath(imageThreshHoldValue) + } else { + screenShotDao.fetchAllScreenShotsPath() + } + clearScreenShot(screenShotPathList) + try { + if (isAppInBackground) { + ScreenShotStorageHelper.clearAll() + screenShotDao.deleteAllScreenShot() + isAppInBackground = false + hasRecordingStarted = false + } else { + val idList = screenShotPathList.map { it.id } + screenShotDao.deleteScreenShot(idList) + ScreenShotStorageHelper.deleteKItems(idList.size) + } + } catch (e: Exception) { + e.log() + } } catch (e: Exception) { e.log() } @@ -595,15 +580,20 @@ object AlfredManager { Gson().fromJson(detailsList.toString(), listType) if (events.size > 0) { val sessionId = events.first().sessionId - val request = EventMetricRequest( - baseAttribute = BaseAttribute(sessionId = sessionId), - metricsAttribute = events - ) - val response = repository.eventMetric( - AlfredConstants.DEFAULT_INGEST_METRIC_URL, - metricRequestBody = request - ) - return if ((response.isSuccessful && response.code() == CODE_API_SUCCESS) or (response.code() == CODE_API_BAD_REQUEST)) { + val request = + EventMetricRequest( + baseAttribute = BaseAttribute(sessionId = sessionId), + metricsAttribute = events + ) + val response = + repository.eventMetric( + AlfredConstants.DEFAULT_INGEST_METRIC_URL, + metricRequestBody = request + ) + return if ( + (response.isSuccessful && response.code() == CODE_API_SUCCESS) or + (response.code() == CODE_API_BAD_REQUEST) + ) { apiMetricDao.deleteApiMetric(metricEventList.map { it.id }) true } else { @@ -623,50 +613,23 @@ object AlfredManager { } private fun startSyncEvents(applicationContext: Context) { - timer = fixedRateTimer( - AlfredConstants.TIMER_THREAD_NAME, - false, - AlfredConstants.DEFAULT_INITIAL_DELAY, - config.getEventsDelayInMilliseconds() - ) { - runBlocking { - AddMetricTask.resetEventCount() - sendIngestMetric() - AddEventTask.resetEventCount() - sendEventsToServer(applicationContext) + timer = + fixedRateTimer( + AlfredConstants.TIMER_THREAD_NAME, + false, + AlfredConstants.DEFAULT_INITIAL_DELAY, + config.getEventsDelayInMilliseconds() + ) { + runBlocking { + AddMetricTask.resetEventCount() + sendIngestMetric() + AddEventTask.resetEventCount() + sendEventsToServer(applicationContext) + } } - } } - fun handleScreenTransitionEvent( - currentScreenName: String?, previousScreenName: String?, screenTransitionDuration: Long - ) { - if (config.getAlfredStatus() && config.getMetricsApiEnableStatus()) { - val screenTransitionAttributes: HashMap = hashMapOf() - screenTransitionAttributes.apply { - this[AlfredConstants.CURRENT_SCREEN_NAME] = currentScreenName.orEmpty() - this[AlfredConstants.PREVIOUS_SCREEN_NAME] = previousScreenName.orEmpty() - this[AlfredConstants.LOAD_TIME] = screenTransitionDuration - } - coroutineDispatcher.executor.execute { - val screenTransitionEvent = buildAppPerformanceEvent( - eventName = AlfredConstants.SCREEN_TRANSITION_METRICS, - attribute = screenTransitionAttributes, - eventType = AlfredConstants.SCREEN_TRANSITION_METRICS - ) - AlfredDispatcher.addTaskToQueue( - AddMetricTask( - screenTransitionEvent, applicationContext - ) - ) - } - } - } - - - suspend fun sendEventsToServer( - applicationContext: Context - ): Boolean { + suspend fun sendEventsToServer(applicationContext: Context): Boolean { if (config.getAlfredStatus() && config.getEnableRecordingStatus()) { mutex.withLock { val db = AlfredDatabaseHelper.getAnalyticsDatabase(applicationContext) @@ -681,15 +644,16 @@ object AlfredManager { Gson().fromJson(detailsList.toString(), listType) if (events.size > 0) { val sessionId = events.first().sessionId - val request = AnalyticsRequest( - baseAttribute = BaseAttribute( - sessionId = sessionId - ), events = events - ) - val response = repository.sendEvents( - config.getPostUrl(), request - ) - return if ((response.isSuccessful && response.code() == CODE_API_SUCCESS) or (response.code() == CODE_API_BAD_REQUEST)) { + val request = + AnalyticsRequest( + baseAttribute = BaseAttribute(sessionId = sessionId), + events = events + ) + val response = repository.sendEvents(config.getPostUrl(), request) + return if ( + (response.isSuccessful && response.code() == CODE_API_SUCCESS) or + (response.code() == CODE_API_BAD_REQUEST) + ) { analyticsDao.deleteEvents(analyticsEvents.map { it.eventId }) true } else { @@ -710,12 +674,7 @@ object AlfredManager { return false } - private fun sendAlfredSessionEvent( - dumpFlow: Boolean = false, index: Int? = null, - alfredSessionId: String? = null, - eventStartRecordingTime: Long? = null, - sessionStartRecordingTime: Long? = null - ) { + private fun sendAlfredSessionEvent(dumpFlow: Boolean = false, index: Int? = null) { var request: SessionRequest? = null if (dumpFlow) { var clientTs: Long? = null @@ -727,54 +686,61 @@ object AlfredManager { sessionTimeStamp = zipFileDetail.sessionStartRecordingTime sessionId = zipFileDetail.alfredSessionId } else { - clientTs = eventStartRecordingTime - sessionTimeStamp = sessionStartRecordingTime - sessionId = alfredSessionId + clientTs = eventStartRecordingTimeForCrash + sessionTimeStamp = sessionStartRecordingTimeForCrash + sessionId = sessionIdForCrash } - request = SessionRequest( - base_attribute = BaseAttribute( - sessionId = sessionId, - eventTimeStamp = config.getEventTimeStamp(), - clientTs = clientTs, - sessionTimeStamp = sessionTimeStamp - ), session_upload_event_attributes = SessionEventAttribute( - beginningDeviceAttributes = DeviceAttributes(), - endDeviceAttributes = DeviceAttributes() + request = + SessionRequest( + base_attribute = + BaseAttribute( + sessionId = sessionId, + eventTimeStamp = config.getEventTimeStamp(), + clientTs = clientTs, + sessionTimeStamp = sessionTimeStamp + ), + session_upload_event_attributes = + SessionEventAttribute( + beginningDeviceAttributes = DeviceAttributes(), + endDeviceAttributes = DeviceAttributes() + ) ) - ) } else { - request = SessionRequest( - base_attribute = BaseAttribute( - sessionId = config.getAlfredSessionId(), - eventTimeStamp = config.getEventTimeStamp(), - clientTs = config.getEventStartRecordingTime() - ), session_upload_event_attributes = SessionEventAttribute( - beginningDeviceAttributes = DeviceAttributes( - battery = config.batteryPercentageBeforeEventStart, - cpu = config.cpuUsageBeforeEventStart, - memory = config.memoryUsageBeforeEventStart, - storage = config.storageUsageBeforeEventStart - ), endDeviceAttributes = DeviceAttributes( - battery = config.getBatteryPercentage(), - cpu = config.getCpuUsage(), - memory = config.getMemoryUsage(), - storage = config.getStorageUsage() - ) + request = + SessionRequest( + base_attribute = + BaseAttribute( + sessionId = config.getAlfredSessionId(), + eventTimeStamp = config.getEventTimeStamp(), + clientTs = config.getEventStartRecordingTime() + ), + session_upload_event_attributes = + SessionEventAttribute( + beginningDeviceAttributes = + DeviceAttributes( + battery = config.batteryPercentageBeforeEventStart, + cpu = config.cpuUsageBeforeEventStart, + memory = config.memoryUsageBeforeEventStart, + storage = config.storageUsageBeforeEventStart + ), + endDeviceAttributes = + DeviceAttributes( + battery = config.getBatteryPercentage(), + cpu = config.getCpuUsage(), + memory = config.getMemoryUsage(), + storage = config.getStorageUsage() + ) + ) ) - ) } coroutineScope.launch { - repository.sendSession( - AlfredConstants.DEFAULT_SEND_SESSION_POST_URL, request - ) + repository.sendSession(AlfredConstants.DEFAULT_SEND_SESSION_POST_URL, request) if (!dumpFlow) { config.setEventStartRecordingTime(true) handleDeviceAttributes() } else { - index?.let { index -> - zipDetailsDao.deleteZipFileDetail(zipFileDetails[index].id) - } - if(workFailureData.size>0){ + index?.let { index -> zipDetailsDao.deleteZipFileDetail(zipFileDetails[index].id) } + if (workFailureData.size > 0) { workFailureData.removeAt(0) } } @@ -808,63 +774,40 @@ object AlfredManager { coroutineDispatcher.executor.execute { val duration: Long = endTime - startTime val errorType: String? = null - val errorMessage: String? = if (response.code != CODE_API_SUCCESS) { - response.message - } else { - null - } - var url= request.url.toString().split("?").first() - request.header(ALFRED)?.let {pathParam -> - if(url.contains(pathParam)){ - url=url.replace(pathParam,"Path_Param_Value") - request.header(X_TARGET)?.let {xTarget -> - url=xTarget.plus(url) - } + val errorMessage: String? = + if (response.code != CODE_API_SUCCESS) { + response.message + } else { + null } - } - Log.d("ALFREDAPI","URL$url") - Log.d("ALFREDAPI","RESPONSE BODY${response.message}") - val attributes = hashMapOf().apply { - this[AlfredConstants.URL] = url - this[AlfredConstants.METHOD] = request.method - this[AlfredConstants.RESPONSE_CODE] = response.code - this[AlfredConstants.ERROR_MESSAGE] = errorMessage.toString() - this[AlfredConstants.ERROR_TYPE] = errorType.toString() - this[AlfredConstants.START_TIME] = startTime - this[AlfredConstants.END_TIME] = endTime - this[AlfredConstants.DURATION_IN_MS] = duration.toDouble() - this[AlfredConstants.BYTES_RECEIVED] = byteReceived - this[AlfredConstants.BYTES_SENT] = byteSent - if (config.getApiResponseEnableStatus()) { - if (response.code != CODE_API_SUCCESS || config.getEnabledApiPath() - ?.contains(url) == true - ) { - Log.d("ALFREDAPI","response${response.body.toString()}") - this[AlfredConstants.RESPONSE_BODY] = response.body.toString() - } + val attributes = + hashMapOf().apply { + this[AlfredConstants.URL] = request.url.toString() + this[AlfredConstants.METHOD] = request.method + this[AlfredConstants.RESPONSE_CODE] = response.code + this[AlfredConstants.ERROR_MESSAGE] = errorMessage.toString() + this[AlfredConstants.ERROR_TYPE] = errorType.toString() + this[AlfredConstants.START_TIME] = startTime + this[AlfredConstants.END_TIME] = endTime + this[AlfredConstants.DURATION_IN_MS] = duration.toDouble() + this[AlfredConstants.BYTES_RECEIVED] = byteReceived + this[AlfredConstants.BYTES_SENT] = byteSent } - if (config.getApiRequestEnableStatus()) { - if (response.code != CODE_API_SUCCESS || config.getEnabledApiPath() - ?.contains(url) == true - ) { - Log.d("ALFREDAPI","request${request.body.toString()}") - this[AlfredConstants.REQUEST_BODY] = request.body.toString() - } - } - } - val appPerformanceEvent = buildAppPerformanceEvent( - AlfredConstants.API_METRIC_EVENT_NAME, API_METRICS, attributes - ) - AlfredDispatcher.addTaskToQueue( - AddMetricTask( - appPerformanceEvent, applicationContext + val appPerformanceEvent = + buildAppPerformanceEvent( + AlfredConstants.API_METRIC_EVENT_NAME, + API_METRICS, + attributes ) + AlfredDispatcher.addTaskToQueue( + AddMetricTask(appPerformanceEvent, applicationContext) ) } } } fun stopRecording(appBackgroundView: View) { + isAppInBackground = true hasRecordingStarted = false screenShotTimer?.cancel() if (config.getAlfredStatus() && config.getEnableRecordingStatus()) { @@ -882,6 +825,9 @@ object AlfredManager { eventStartRecordingTime: Long? = null, index: Int? = null ) { + sessionIdForCrash = alfredSessionId + sessionStartRecordingTimeForCrash = sessionStartRecordingTime + eventStartRecordingTimeForCrash = eventStartRecordingTime val fileList = ArrayList() imagePathList.forEach { screenShotPathHelper -> screenShotPathHelper.screenShotPath?.let { screenShotPath -> @@ -893,25 +839,14 @@ object AlfredManager { val zipFilePath = applicationContext.filesDir.path + "/" + zipFileName if (zip(fileList, zipFilePath) == true) { clearScreenShot(imagePathList) - getPreSignedUrl( - zipFileName, - index = index, - workManagerFlow = true, - dumpFlow = true, - alfredSessionId = alfredSessionId, - eventStartRecordingTime = eventStartRecordingTime, - sessionStartRecordingTime = sessionStartRecordingTime - ) + getPreSignedUrl(zipFileName, index = index, workManagerFlow = true, dumpFlow = true) } } - private fun toZip( - imagePathList: List - ) { + private fun toZip(imagePathList: List) { val zipFileName = config.getAlfredSessionId() + UUID.randomUUID().toString() config.setZipFileName(zipFileName) - val zipFilePath: String = - applicationContext.filesDir.path + "/" + zipFileName + val zipFilePath: String = applicationContext.filesDir.path + "/" + zipFileName val fileList = ArrayList() imagePathList.forEach { screenShotPathHelper -> screenShotPathHelper.screenShotPath?.let { screenShotPath -> @@ -921,7 +856,7 @@ object AlfredManager { } } if (zip(fileList, zipFilePath) == true) { - deleteScreenShot(imagePathList) + deleteScreenShot() config.setNextEventStartRecordingTime() } } @@ -943,12 +878,13 @@ object AlfredManager { if (currentTouchEvent?.action == ACTION_UP) { val touchEventData = getTouchEvent(currentTouchEvent, previousTouchEvent) - val event = buildEvent( - touchEventData.first, - touchEventData.second, - screenName = screenName, - moduleName = moduleName - ) + val event = + buildEvent( + touchEventData.first, + touchEventData.second, + screenName = screenName, + moduleName = moduleName + ) AlfredDispatcher.addTaskToQueue(AddEventTask(event, applicationContext)) } } catch (e: Exception) { @@ -963,11 +899,7 @@ object AlfredManager { if (ScreenShotStorageHelper.images.size > 0) { coroutineScope.launch(Dispatchers.IO) { var bmp: Bitmap? = null - val screenShotCapture = async { - bmp = captureScreenshotOfCustomView( - view - ) - } + val screenShotCapture = async { bmp = captureScreenshotOfCustomView(view) } screenShotCapture.await() val insertScreenShotInDb = async { insertScreenShotPathInDb(this, applicationContext, bmp) @@ -979,33 +911,36 @@ object AlfredManager { } fun handleAnrEvent( - anrEventProperties: Map, anrView: View, screenName: String? = null + anrEventProperties: Map, + anrView: View, + screenName: String? = null ) { startAnrCrashZipUpload(anrView) if (config.getAlfredSessionId().isNotEmpty()) { coroutineDispatcher.executor.execute { - val event = buildEvent( - AlfredConstants.ANR_EVENT, anrEventProperties as HashMap, - screenName = screenName, - moduleName = currentModuleName - ) - AlfredDispatcher.addTaskToQueue(AddEventTask(event, applicationContext)) + val event = + buildEvent( + AlfredConstants.ANR_EVENT, + anrEventProperties as HashMap, + screenName = screenName, + moduleName = currentModuleName + ) + AlfredDispatcher.addTaskToQueue(AddEventTask(event, this.applicationContext)) } } } - fun handleSWWEvent( - screenName: String? = null, swwEventProperties: Map - ) { + fun handleSWWEvent(screenName: String? = null, swwEventProperties: Map) { if (config.getAlfredStatus() && config.getEnableRecordingStatus()) { if (config.getAlfredSessionId().isNotEmpty()) { coroutineDispatcher.executor.execute { - val event = buildEvent( - AlfredConstants.ERROR_LOG, - swwEventProperties as HashMap, - screenName = screenName, - moduleName = currentModuleName - ) + val event = + buildEvent( + AlfredConstants.ERROR_LOG, + swwEventProperties as HashMap, + screenName = screenName, + moduleName = currentModuleName + ) AlfredDispatcher.addTaskToQueue(AddEventTask(event, applicationContext)) } } @@ -1020,12 +955,13 @@ object AlfredManager { startAnrCrashZipUpload(crashView) if (config.getAlfredSessionId().isNotEmpty()) { coroutineDispatcher.executor.execute { - val event = buildEvent( - AlfredConstants.CRASH_ANALYTICS_EVENT, - crashEventProperties as HashMap, - screenName = screenName, - moduleName = currentModuleName - ) + val event = + buildEvent( + AlfredConstants.CRASH_ANALYTICS_EVENT, + crashEventProperties as HashMap, + screenName = screenName, + moduleName = currentModuleName + ) AlfredDispatcher.addTaskToQueue(AddEventTask(event, applicationContext)) } } @@ -1039,33 +975,44 @@ object AlfredManager { moduleName: String? = null ): AnalyticsEvent { val timeStamp = System.currentTimeMillis() - val eventData = EventAttribute( - eventName = eventName, - eventType = eventName, - eventTimestamp = timeStamp, - attributes = properties, - sessionId = config.getAlfredSessionId(), - screenName = screenName, - moduleName = moduleName - ) + val eventData = + EventAttribute( + eventName = eventName, + eventType = eventName, + eventTimestamp = timeStamp, + attributes = properties, + sessionId = config.getAlfredSessionId(), + screenName = screenName, + moduleName = moduleName + ) return AnalyticsEvent(timeStamp, Gson().toJson(eventData)) } @WorkerThread fun buildAppPerformanceEvent( - eventName: String, eventType: String, attribute: HashMap? = null + eventName: String, + eventType: String, + attribute: HashMap? = null ): ApiMetricHelper { val timeStamp = System.currentTimeMillis() - val metricData = MetricAttribute( - eventId = config.getAlfredEventId(), - eventName = eventName, - eventType = eventType, - sessionId = config.getAlfredSessionId(), - attributes = attribute, - screenName = currentScreenName, - moduleName = currentModuleName - ) + val metricData = + MetricAttribute( + eventId = config.getAlfredEventId(), + eventName = eventName, + eventType = eventType, + sessionId = config.getAlfredSessionId(), + attributes = attribute, + screenName = currentScreenName, + moduleName = currentModuleName + ) return ApiMetricHelper(timeStamp, Gson().toJson(metricData)) } + fun setCurrentScreenName(screenName: String?) { + currentScreenName = screenName + } + + fun getCurrentScreenName(): String? { + return currentScreenName + } } diff --git a/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabase.kt b/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabase.kt index 1678581..352730f 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabase.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabase.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2022-2023 by Navi Technologies Limited + * * Copyright © 2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -18,14 +18,22 @@ import com.navi.alfred.db.model.ScreenShotPathHelper import com.navi.alfred.db.model.ZipDetailsHelper @Database( - entities = [AnalyticsEvent::class, ScreenShotPathHelper::class, ZipDetailsHelper::class, ApiMetricHelper::class], + entities = + [ + AnalyticsEvent::class, + ScreenShotPathHelper::class, + ZipDetailsHelper::class, + ApiMetricHelper::class + ], version = 3, exportSchema = true ) - abstract class AlfredDatabase : RoomDatabase() { abstract fun analyticsDao(): AnalyticsDAO + abstract fun screenShotDao(): ScreenShotDao + abstract fun zipDetailsDao(): ZipDetailsDao + abstract fun apiMetricDao(): ApiMetricDao } diff --git a/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabaseHelper.kt b/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabaseHelper.kt index c480370..818f225 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabaseHelper.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabaseHelper.kt @@ -21,11 +21,11 @@ object AlfredDatabaseHelper { INSTANCE } val instance = - Room.databaseBuilder(context, AlfredDatabase::class.java, EVENT_DB_NAME).fallbackToDestructiveMigration() + Room.databaseBuilder(context, AlfredDatabase::class.java, EVENT_DB_NAME) + .fallbackToDestructiveMigration() .build() INSTANCE = instance instance } } - } diff --git a/navi-alfred/src/main/java/com/navi/alfred/db/dao/AlfredDao.kt b/navi-alfred/src/main/java/com/navi/alfred/db/dao/AlfredDao.kt index 40e80ce..7871445 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/db/dao/AlfredDao.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/db/dao/AlfredDao.kt @@ -18,8 +18,7 @@ import com.navi.alfred.db.model.ZipDetailsHelper @Dao interface AnalyticsDAO { - @Insert - fun insertEvent(event: AnalyticsEvent) + @Insert fun insertEvent(event: AnalyticsEvent) @Query("SELECT * FROM AnalyticsEvent ORDER BY time ASC LIMIT :thresholdValue") fun fetchEvents(thresholdValue: Int): List @@ -27,9 +26,7 @@ interface AnalyticsDAO { @Query("DELETE FROM AnalyticsEvent WHERE eventId IN (:idList)") fun deleteEvents(idList: List) - @Query("SELECT count(*) FROM AnalyticsEvent") - fun getEventCount(): Int - + @Query("SELECT count(*) FROM AnalyticsEvent") fun getEventCount(): Int } @Dao @@ -47,37 +44,30 @@ interface ScreenShotDao { @Query("DELETE FROM ScreenShotPathHelper WHERE id IN (:idList)") fun deleteScreenShot(idList: List) - @Query("DELETE FROM ScreenShotPathHelper") - fun deleteAllScreenShot() + @Query("DELETE FROM ScreenShotPathHelper") fun deleteAllScreenShot() - @Query("SELECT count(*) FROM ScreenShotPathHelper") - fun getScreenShotCount(): Int + @Query("SELECT count(*) FROM ScreenShotPathHelper") fun getScreenShotCount(): Int } @Dao -interface ZipDetailsDao{ +interface ZipDetailsDao { - @Insert(onConflict = OnConflictStrategy.REPLACE) - fun insert(data: ZipDetailsHelper) + @Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(data: ZipDetailsHelper) - @Query("SELECT count(*) FROM ZipDetailsHelper") - fun getZipFilesDetailsCount(): Int + @Query("SELECT count(*) FROM ZipDetailsHelper") fun getZipFilesDetailsCount(): Int @Query("SELECT * FROM ZipDetailsHelper ORDER BY sessionStartRecordingTime") fun fetchAllZipFilesDetails(): List - @Query("DELETE FROM ZipDetailsHelper WHERE id = :id") - fun deleteZipFileDetail(id: Int) + @Query("DELETE FROM ZipDetailsHelper WHERE id = :id") fun deleteZipFileDetail(id: Int) } @Dao interface ApiMetricDao { - @Insert(onConflict = OnConflictStrategy.REPLACE) - fun insert(data: ApiMetricHelper) + @Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(data: ApiMetricHelper) - @Query("SELECT count(*) FROM ApiMetricHelper") - fun getApiMetricCount(): Int + @Query("SELECT count(*) FROM ApiMetricHelper") fun getApiMetricCount(): Int @Query("SELECT * FROM ApiMetricHelper ORDER BY time ASC LIMIT :thresholdValue") fun fetchApiMetric(thresholdValue: Int): List diff --git a/navi-alfred/src/main/java/com/navi/alfred/db/model/AlfredEntity.kt b/navi-alfred/src/main/java/com/navi/alfred/db/model/AlfredEntity.kt index 2001a8b..0abb4bd 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/db/model/AlfredEntity.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/db/model/AlfredEntity.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2022-2023 by Navi Technologies Limited + * * Copyright © 2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -16,8 +16,7 @@ data class AnalyticsEvent( @ColumnInfo(name = "time") val time: Long?, @ColumnInfo(name = "details") val details: String? ) { - @PrimaryKey(autoGenerate = true) - var eventId: Int = 0 + @PrimaryKey(autoGenerate = true) var eventId: Int = 0 } @Entity @@ -25,8 +24,7 @@ data class ScreenShotPathHelper( @ColumnInfo(name = "time") val time: Long?, @ColumnInfo(name = "screenShotPath") val screenShotPath: String? ) { - @PrimaryKey(autoGenerate = true) - var id: Int = 0 + @PrimaryKey(autoGenerate = true) var id: Int = 0 } @Entity @@ -37,8 +35,7 @@ data class ZipDetailsHelper( @ColumnInfo(name = "eventStartRecordingTime") val eventStartRecordingTime: Long, @ColumnInfo(name = "zipFileName") val zipFileName: String ) { - @PrimaryKey(autoGenerate = true) - var id: Int = 0 + @PrimaryKey(autoGenerate = true) var id: Int = 0 } @Entity @@ -46,8 +43,7 @@ data class ApiMetricHelper( @ColumnInfo(name = "time") val time: Long?, @ColumnInfo(name = "metric") val metric: String? ) { - @PrimaryKey(autoGenerate = true) - var id: Int = 0 + @PrimaryKey(autoGenerate = true) var id: Int = 0 } class Converter { @@ -61,8 +57,4 @@ class Converter { fun toDeviceAttributes(data: String): DeviceAttributes { return Gson().fromJson(data, DeviceAttributes::class.java) } - } - - - diff --git a/navi-alfred/src/main/java/com/navi/alfred/deserializer/AnalyticsDataDeserializer.kt b/navi-alfred/src/main/java/com/navi/alfred/deserializer/AnalyticsDataDeserializer.kt index 4fb67b0..494b317 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/deserializer/AnalyticsDataDeserializer.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/deserializer/AnalyticsDataDeserializer.kt @@ -1,3 +1,10 @@ +/* + * + * * Copyright © 2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + package com.navi.alfred.deserializer import com.google.gson.JsonDeserializationContext @@ -8,11 +15,13 @@ import java.lang.reflect.Type class AnalyticsDataDeserializer : JsonDeserializer { override fun deserialize( - json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext? + json: JsonElement?, + typeOfT: Type?, + context: JsonDeserializationContext? ): AnalyticsRequest? { json?.let { return context?.deserialize(json, AnalyticsRequest::class.java) } return null } -} \ No newline at end of file +} diff --git a/navi-alfred/src/main/java/com/navi/alfred/deserializer/MetricsDataDeserializer.kt b/navi-alfred/src/main/java/com/navi/alfred/deserializer/MetricsDataDeserializer.kt index 4cbe4cb..175e002 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/deserializer/MetricsDataDeserializer.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/deserializer/MetricsDataDeserializer.kt @@ -1,3 +1,10 @@ +/* + * + * * Copyright © 2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + package com.navi.alfred.deserializer import com.google.gson.JsonDeserializationContext @@ -8,11 +15,13 @@ import java.lang.reflect.Type class MetricsDataDeserializer : JsonDeserializer { override fun deserialize( - json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext? + json: JsonElement?, + typeOfT: Type?, + context: JsonDeserializationContext? ): EventMetricRequest? { json?.let { return context?.deserialize(json, EventMetricRequest::class.java) } return null } -} \ No newline at end of file +} diff --git a/navi-alfred/src/main/java/com/navi/alfred/deserializer/SessionDataDeserializer.kt b/navi-alfred/src/main/java/com/navi/alfred/deserializer/SessionDataDeserializer.kt index fb1d72a..69249bf 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/deserializer/SessionDataDeserializer.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/deserializer/SessionDataDeserializer.kt @@ -1,3 +1,10 @@ +/* + * + * * Copyright © 2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + package com.navi.alfred.deserializer import com.google.gson.JsonDeserializationContext @@ -9,11 +16,13 @@ import java.lang.reflect.Type class SessionDataDeserializer : JsonDeserializer { override fun deserialize( - json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext? + json: JsonElement?, + typeOfT: Type?, + context: JsonDeserializationContext? ): SessionRequest? { json?.let { return context?.deserialize(json, EventMetricRequest::class.java) } return null } -} \ No newline at end of file +} diff --git a/navi-alfred/src/main/java/com/navi/alfred/dispatcher/AlfredDispatcher.kt b/navi-alfred/src/main/java/com/navi/alfred/dispatcher/AlfredDispatcher.kt index a55efcf..419b27c 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/dispatcher/AlfredDispatcher.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/dispatcher/AlfredDispatcher.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2019-2023 by Navi Technologies Limited + * * Copyright © 2021-2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -10,18 +10,15 @@ package com.navi.alfred.dispatcher import com.navi.alfred.worker.AnalyticsTask import com.navi.alfred.worker.AnalyticsTaskProcessor -/** - * handles task of putting events into DB and syncing data with backend - */ +/** handles task of putting events into DB and syncing data with backend */ object AlfredDispatcher { private val taskProcessor: AnalyticsTaskProcessor = AnalyticsTaskProcessor() + fun addTaskToQueue(task: AnalyticsTask) { taskProcessor.addTask(task) } - /** - * Executes task in a different thread than the Queue - */ + /** Executes task in a different thread than the Queue */ fun executeInNewThread(task: AnalyticsTask) { taskProcessor.executeInNewThread(task) } diff --git a/navi-alfred/src/main/java/com/navi/alfred/model/ErrorMessage.kt b/navi-alfred/src/main/java/com/navi/alfred/model/ErrorMessage.kt index c6fa755..fa0823e 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/model/ErrorMessage.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/model/ErrorMessage.kt @@ -1,13 +1,16 @@ +/* + * + * * Copyright © 2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + package com.navi.alfred.model import com.navi.alfred.db.model.ScreenShotPathHelper import java.util.* - -data class ErrorMessage( - var statusCode: Int? = null, - var message: String? = null -) +data class ErrorMessage(var statusCode: Int? = null, var message: String? = null) data class WorkManagerFailureInputData( var alfredSessionId: String? = "", @@ -15,4 +18,4 @@ data class WorkManagerFailureInputData( var eventStartRecordingTime: Long = 0L, var screenShots: List = emptyList(), val id: UUID -) \ No newline at end of file +) diff --git a/navi-alfred/src/main/java/com/navi/alfred/model/EventMetricRequest.kt b/navi-alfred/src/main/java/com/navi/alfred/model/EventMetricRequest.kt index e322086..436f2be 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/model/EventMetricRequest.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/model/EventMetricRequest.kt @@ -1,3 +1,10 @@ +/* + * + * * Copyright © 2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + package com.navi.alfred.model import com.google.gson.annotations.SerializedName @@ -16,5 +23,3 @@ data class MetricAttribute( @SerializedName("module_name") val moduleName: String? = null, @SerializedName("attributes") val attributes: HashMap? = null ) - - diff --git a/navi-alfred/src/main/java/com/navi/alfred/model/SessionRequest.kt b/navi-alfred/src/main/java/com/navi/alfred/model/SessionRequest.kt index 2f5fca8..3af06b8 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/model/SessionRequest.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/model/SessionRequest.kt @@ -1,3 +1,10 @@ +/* + * + * * Copyright © 2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + package com.navi.alfred.model import com.google.gson.annotations.SerializedName @@ -21,32 +28,43 @@ data class EventAttribute( data class SessionRequest( @SerializedName("base_attributes") val base_attribute: BaseAttribute, - @SerializedName("session_upload_event_attributes") val session_upload_event_attributes: SessionEventAttribute + @SerializedName("session_upload_event_attributes") + val session_upload_event_attributes: SessionEventAttribute ) data class BaseAttribute( - @SerializedName("app_version_code") val appVersionCode: String = AlfredManager.config.getAppVersionCode(), - @SerializedName("app_version_name") val appVersionName: String? = AlfredManager.config.getAppVersionName(), - @SerializedName("client_ts") val clientTs: Long? = AlfredManager.config.getEventStartRecordingTime(), + @SerializedName("app_version_code") + val appVersionCode: String = AlfredManager.config.getAppVersionCode(), + @SerializedName("app_version_name") + val appVersionName: String? = AlfredManager.config.getAppVersionName(), + @SerializedName("client_ts") + val clientTs: Long? = AlfredManager.config.getEventStartRecordingTime(), @SerializedName("device_id") val deviceId: String? = AlfredManager.config.getDeviceId(), - @SerializedName("device_model") val deviceModel: String? = AlfredManager.config.getDeviceModel(), - @SerializedName("device_manufacturer") val deviceManufacturer: String? = AlfredManager.config.getManufacturer(), + @SerializedName("device_model") + val deviceModel: String? = AlfredManager.config.getDeviceModel(), + @SerializedName("device_manufacturer") + val deviceManufacturer: String? = AlfredManager.config.getManufacturer(), @SerializedName("app_os") val appOs: String? = AlfredManager.config.getOs(), @SerializedName("os_version") val osVersion: String? = AlfredManager.config.getOsVersion(), @SerializedName("latitude") val latitude: Double? = AlfredManager.config.getLatitude(), @SerializedName("longitude") val longitude: Double? = AlfredManager.config.getLongitude(), @SerializedName("customer_id") val customerId: String? = AlfredManager.config.getUserId(), @SerializedName("up_time") val upTime: Long? = null, - @SerializedName("carrier_name") val carrierName: String? = AlfredManager.config.getNetworkCarrier(), + @SerializedName("carrier_name") + val carrierName: String? = AlfredManager.config.getNetworkCarrier(), @SerializedName("parent_session_id") val parentSessionId: String? = null, - @SerializedName("event_timestamp") val eventTimeStamp: Long? = AlfredManager.config.getEventTimeStamp(), - @SerializedName("session_id") val sessionId: String? = AlfredManager.config.getAlfredSessionId(), - @SerializedName("session_time_stamp") val sessionTimeStamp: Long? = AlfredManager.config.getSessionStartRecordingTime(), + @SerializedName("event_timestamp") + val eventTimeStamp: Long? = AlfredManager.config.getEventTimeStamp(), + @SerializedName("session_id") + val sessionId: String? = AlfredManager.config.getAlfredSessionId(), + @SerializedName("session_time_stamp") + val sessionTimeStamp: Long? = AlfredManager.config.getSessionStartRecordingTime(), ) data class SessionEventAttribute( @SerializedName("event_id") val eventId: String? = AlfredManager.config.getAlfredEventId(), - @SerializedName("beginning_device_attributes") val beginningDeviceAttributes: DeviceAttributes? = null, + @SerializedName("beginning_device_attributes") + val beginningDeviceAttributes: DeviceAttributes? = null, @SerializedName("end_device_attributes") val endDeviceAttributes: DeviceAttributes? = null ) @@ -55,4 +73,4 @@ data class DeviceAttributes( @SerializedName("cpu") val cpu: Float? = null, @SerializedName("storage") val storage: Float? = null, @SerializedName("memory") val memory: Float? = null, -) \ No newline at end of file +) diff --git a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredNetworkRepository.kt b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredNetworkRepository.kt index 904ae9a..0001f67 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredNetworkRepository.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredNetworkRepository.kt @@ -18,7 +18,8 @@ import retrofit2.Response class AlfredNetworkRepository { suspend fun sendEvents( - url: String, analyticsRequest: AnalyticsRequest + url: String, + analyticsRequest: AnalyticsRequest ): Response { return AlfredRetrofitProvider.getApiService() .sendEvents(url, "application/json", ALFRED, analyticsRequest) @@ -28,37 +29,34 @@ class AlfredNetworkRepository { return AlfredRetrofitProvider.getApiService().getPreSignedUrl(sessionId, ALFRED) } - suspend fun sendSession( - url: String, - sessionRequest: SessionRequest - ): Response { + suspend fun sendSession(url: String, sessionRequest: SessionRequest): Response { return AlfredRetrofitProvider.getApiService() .sendSession(url, "application/json", ALFRED, sessionRequest) } - suspend fun uploadZipToS3( - preSignedUrl: String, request: RequestBody - ): Response { + suspend fun uploadZipToS3(preSignedUrl: String, request: RequestBody): Response { return AlfredRetrofitProvider.getApiService().uploadToS3(preSignedUrl, request, ALFRED) } - suspend fun eventMetric( - url: String, metricRequestBody: EventMetricRequest - ): Response { + suspend fun eventMetric(url: String, metricRequestBody: EventMetricRequest): Response { return AlfredRetrofitProvider.getApiService() .sendMetric(url, ALFRED, "application/json", metricRequestBody) } suspend fun cruiseConfig( - url: String, appVersionName: String, osVersionCode: String, deviceId: String + url: String, + appVersionName: String, + osVersionCode: String, + deviceId: String ): Response { - return AlfredRetrofitProvider.getApiService().getCruiseConfig( + return AlfredRetrofitProvider.getApiService() + .getCruiseConfig( url, - ALFRED, + ALFRED, contentType = "application/json", appVersionName = appVersionName, osVersion = osVersionCode, deviceId = deviceId ) } -} \ No newline at end of file +} diff --git a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitProvider.kt b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitProvider.kt index 80842be..9b4a831 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitProvider.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitProvider.kt @@ -12,10 +12,10 @@ import com.chuckerteam.chucker.api.ChuckerCollector import com.chuckerteam.chucker.api.ChuckerInterceptor import com.google.gson.GsonBuilder import com.navi.alfred.AlfredManager +import com.navi.alfred.BuildConfig import com.navi.alfred.deserializer.AnalyticsDataDeserializer import com.navi.alfred.deserializer.MetricsDataDeserializer import com.navi.alfred.deserializer.SessionDataDeserializer -import com.navi.alfred.model.AnalyticsRequest import com.navi.alfred.model.EventMetricRequest import com.navi.alfred.model.SessionRequest import com.navi.alfred.utils.handleException @@ -34,64 +34,79 @@ object AlfredRetrofitProvider { private lateinit var apiService: AlfredRetrofitService private lateinit var okHttpClient: OkHttpClient - private val headerInterceptor: Interceptor get() = Interceptor { chain -> val request = chain.request() - val response = try { - chain.proceed(request).newBuilder().build() - } catch (e: Exception) { - val errorMessage = handleException(e) - // A mocked response in case of n/w exception - Response.Builder().request(request).protocol(Protocol.HTTP_2) - .code(errorMessage.statusCode.orZero()) - .body(ResponseBody.create("application/json".toMediaTypeOrNull(), "{}")) - .message(errorMessage.message.orEmpty()).build() - } + val response = + try { + chain.proceed(request).newBuilder().build() + } catch (e: Exception) { + val errorMessage = handleException(e) + // A mocked response in case of n/w exception + Response.Builder() + .request(request) + .protocol(Protocol.HTTP_2) + .code(errorMessage.statusCode.orZero()) + .body(ResponseBody.create("application/json".toMediaTypeOrNull(), "{}")) + .message(errorMessage.message.orEmpty()) + .build() + } response } - fun init(context: Context) { - okHttpClient = OkHttpClient.Builder().apply { - connectTimeout(30, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).writeTimeout(30,TimeUnit.SECONDS) - if (BuildConfig.DEBUG && !AlfredManager.config.getDisableAlfredLogsStatus()) { - addInterceptor(loggingInterceptor()) - addInterceptor( - ChuckerInterceptor.Builder(context).collector(ChuckerCollector(context)) - .alwaysReadResponseBody(false).build() - ) - } - addInterceptor(headerInterceptor) - connectionPool(ConnectionPool(0, 5, TimeUnit.MINUTES)) - .protocols(listOf(Protocol.HTTP_1_1)) - }.build() + okHttpClient = + OkHttpClient.Builder() + .apply { + connectTimeout(30, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + if (BuildConfig.DEBUG && !AlfredManager.config.getDisableAlfredLogsStatus()) { + addInterceptor(loggingInterceptor()) + addInterceptor( + ChuckerInterceptor.Builder(context) + .collector(ChuckerCollector(context)) + .alwaysReadResponseBody(false) + .build() + ) + } + addInterceptor(headerInterceptor) + connectionPool(ConnectionPool(0, 5, TimeUnit.MINUTES)) + .protocols(listOf(Protocol.HTTP_1_1)) + } + .build() apiService = getRetrofit().create(AlfredRetrofitService::class.java) } private fun getRetrofit(): Retrofit { - val baseUrl = if (AlfredManager.config.isQa()) { - BASE_URL_QA - } else if (AlfredManager.config.isProd()) { - BASE_URL_PROD - } else { - BASE_URL_DEBUG - } - val providesDeserializer = GsonBuilder().registerTypeAdapter( - AnalyticsRequest::class.java, - AnalyticsDataDeserializer() - ).registerTypeAdapter(SessionRequest::class.java, SessionDataDeserializer()) - .registerTypeAdapter(EventMetricRequest::class.java, MetricsDataDeserializer()).create() - return Retrofit.Builder().baseUrl(baseUrl) + val baseUrl = + if (AlfredManager.config.isQa()) { + BASE_URL_QA + } else if (AlfredManager.config.isProd()) { + BASE_URL_PROD + } else { + BASE_URL_DEBUG + } + val providesDeserializer = + GsonBuilder() + .registerTypeAdapter( + com.navi.alfred.model.AnalyticsRequest::class.java, + AnalyticsDataDeserializer() + ) + .registerTypeAdapter(SessionRequest::class.java, SessionDataDeserializer()) + .registerTypeAdapter(EventMetricRequest::class.java, MetricsDataDeserializer()) + .create() + return Retrofit.Builder() + .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create(providesDeserializer)) - .client(okHttpClient).build() + .client(okHttpClient) + .build() } fun getApiService(): AlfredRetrofitService { return apiService } - private fun loggingInterceptor() = HttpLoggingInterceptor().apply { - setLevel(HttpLoggingInterceptor.Level.BODY) - } + private fun loggingInterceptor() = + HttpLoggingInterceptor().apply { setLevel(HttpLoggingInterceptor.Level.BODY) } } diff --git a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitService.kt b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitService.kt index 7dc8ee3..6e8c324 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitService.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitService.kt @@ -69,4 +69,4 @@ interface AlfredRetrofitService { @Header(DEVICE_ID) deviceId: String, @Header(CONTENT_TYPE) contentType: String, ): Response -} \ No newline at end of file +} diff --git a/navi-alfred/src/main/java/com/navi/alfred/network/model/CruiseResponse.kt b/navi-alfred/src/main/java/com/navi/alfred/network/model/CruiseResponse.kt index ee995f8..628f3f1 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/network/model/CruiseResponse.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/network/model/CruiseResponse.kt @@ -1,13 +1,22 @@ +/* + * + * * Copyright © 2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + package com.navi.alfred.network.model import com.google.gson.annotations.SerializedName data class CruiseResponse( - @SerializedName("data") val data: List, @SerializedName("status") val status: Int + @SerializedName("data") val data: List, + @SerializedName("status") val status: Int ) data class CruiseConfig( - @SerializedName("_id") val id: String, @SerializedName("_source") val source: Source + @SerializedName("_id") val id: String, + @SerializedName("_source") val source: Source ) data class Source( @@ -26,7 +35,8 @@ data class RecordingsConfig( @SerializedName("video_quality") val videoQuality: String? = null, @SerializedName("video_recording_policy") val videoRecordingPolicy: String? = null, @SerializedName("disable_screens") val disableScreens: List? = null, - @SerializedName("disable_modules") val disableModules: List? = null + @SerializedName("disable_modules") val disableModules: List? = null, + @SerializedName("masked_enabled_screens") val maskingEnabledScreens: List? = null ) data class OsConfig( @@ -37,11 +47,8 @@ data class OsConfig( data class MetricsConfig( @SerializedName("disable_api_performance") val disableApiPerformance: Boolean? = null, - @SerializedName("disable_api_response") val disableApiResponse: Boolean? = null, - @SerializedName("enabled_api_paths") val enabledApiPaths: List? = null, - @SerializedName("disable_api_request") val disableApiRequest: Boolean? = null, @SerializedName("disable_cpu_monitoring") val disableCpuMonitoring: Boolean? = null, @SerializedName("disable_memory_monitoring") val disableMemoryMonitoring: Boolean? = null, @SerializedName("disable_remote_logging") val disableRemoteLogging: Boolean? = null, @SerializedName("enable") val enable: Boolean? = null -) \ No newline at end of file +) diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/AlfredConstants.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/AlfredConstants.kt index 93e7e4c..1a5ffc0 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/utils/AlfredConstants.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/utils/AlfredConstants.kt @@ -48,8 +48,6 @@ object AlfredConstants { const val DURATION_IN_MS = "duration_in_ms" const val BYTES_RECEIVED = "bytes_received" const val BYTES_SENT = "bytes_sent" - const val RESPONSE_BODY = "response_body" - const val REQUEST_BODY = "request_body" const val ALFRED = "ALFRED" const val CONTENT_TYPE = "Content-Type" const val X_TARGET = "X-Target" @@ -68,12 +66,9 @@ object AlfredConstants { const val WORKER_ZIP_FILENAME_ENDPOINT = "WORKER_ZIP_FILENAME_ENDPOINT" const val DISABLE_ALFRED_LOGS = "DISABLE_ALFRED_LOGS" const val DISABLE_CDN_LOGS = "DISABLE_CDN_LOGS" - const val CURRENT_SCREEN_NAME = "current_screen_name" - const val PREVIOUS_SCREEN_NAME = "previous_screen_name" - const val LOAD_TIME = "load_time_in_ms" - const val SCREEN_TRANSITION_METRICS = "SCREEN_TRANSITION_METRICS" - const val ZIP_FILE_EXTENSION = ".zip" - const val SYNC_EVENT_TASK = "SyncEventTask" - const val IMAGE_FILE_EXTENSION = ".jpeg" + const val SENSITIVE_VIEW_TAG = "sensitive_view" const val EVENT_DB_NAME = "navi-analytics" + const val ZIP_FILE_EXTENSION = ".zip" + const val IMAGE_FILE_EXTENSION = ".jpeg" + const val SYNC_EVENT_TASK = "SyncEventTask" } diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/ApiConstants.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/ApiConstants.kt index 03bc444..07d1f7f 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/utils/ApiConstants.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/utils/ApiConstants.kt @@ -1,3 +1,10 @@ +/* + * + * * Copyright © 2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + package com.navi.alfred.utils object ApiConstants { @@ -10,4 +17,4 @@ object ApiConstants { const val API_CODE_UNKNOWN_HOST = 21 const val API_CODE_CONNECT_EXCEPTION = 22 const val API_CODE_SOCKET = 26 -} \ No newline at end of file +} diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/Ext.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/Ext.kt index f6fdec8..73e1e73 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/utils/Ext.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/utils/Ext.kt @@ -1,5 +1,13 @@ +/* + * + * * Copyright © 2021-2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + package com.navi.alfred.utils -fun Int?.orZero() = this ?: 0 -fun Boolean?.orFalse() = this ?: false \ No newline at end of file +fun Boolean?.orFalse() = this ?: false + +fun Int?.orZero() = this ?: 0 diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/NetworkUtils.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/NetworkUtils.kt index 7313e49..6d1db1e 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/utils/NetworkUtils.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/utils/NetworkUtils.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2022-2023 by Navi Technologies Limited + * * Copyright © 2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -11,12 +11,10 @@ import com.google.gson.JsonParseException import com.navi.alfred.AlfredManager import com.navi.alfred.model.ErrorMessage import java.net.ConnectException -import java.net.NetworkInterface import java.net.SocketException import java.net.SocketTimeoutException import java.net.UnknownHostException - fun handleException(e: Throwable): ErrorMessage { val errorMessage = ErrorMessage() if (!isNetworkAvailable(AlfredManager.applicationContext)) { @@ -31,29 +29,9 @@ fun handleException(e: Throwable): ErrorMessage { errorMessage.statusCode = ApiConstants.API_WRONG_ERROR_RESPONSE } else if (e is SocketException) { errorMessage.statusCode = ApiConstants.API_CODE_SOCKET - } - else { + } else { errorMessage.statusCode = ApiConstants.API_CODE_ERROR } errorMessage.message = e.message.toString() return errorMessage } - -fun getIPAddress(): String? { - try { - val networkInterfaces = NetworkInterface.getNetworkInterfaces() - while (networkInterfaces.hasMoreElements()) { - val networkInterface = networkInterfaces.nextElement() - val inetAddresses = networkInterface.inetAddresses - while (inetAddresses.hasMoreElements()) { - val inetAddress = inetAddresses.nextElement() - if (!inetAddress.isLoopbackAddress && !inetAddress.isLinkLocalAddress && inetAddress.isSiteLocalAddress) { - return inetAddress.hostAddress - } - } - } - } catch (e: Exception) { - e.printStackTrace() - } - return null -} \ No newline at end of file diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/ScreenShotStorageHelper.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/ScreenShotStorageHelper.kt index 3d9a16e..af11e6e 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/utils/ScreenShotStorageHelper.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/utils/ScreenShotStorageHelper.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2022-2023 by Navi Technologies Limited + * * Copyright © 2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/Utils.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/Utils.kt index e1ad44c..68a4dfb 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/utils/Utils.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/utils/Utils.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2022-2023 by Navi Technologies Limited + * * Copyright © 2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -19,25 +19,26 @@ import android.os.StatFs import android.telephony.TelephonyManager import android.view.MotionEvent import android.view.View +import android.view.ViewGroup import com.google.firebase.crashlytics.FirebaseCrashlytics import com.navi.alfred.AlfredManager import com.navi.alfred.db.AlfredDatabaseHelper import com.navi.alfred.db.model.ScreenShotPathHelper import com.navi.alfred.model.NaviMotionEvent import com.navi.alfred.utils.AlfredConstants.IMAGE_FILE_EXTENSION +import com.navi.alfred.utils.AlfredConstants.SENSITIVE_VIEW_TAG import com.navi.alfred.utils.AlfredConstants.UNDERSCORE -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import timber.log.Timber import java.io.* import java.lang.Math.subtractExact import java.util.* import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream import kotlin.math.abs - +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import timber.log.Timber suspend fun captureScreen( v: View, @@ -53,11 +54,39 @@ suspend fun captureScreen( return null } if (canvas != null && bmp != null) { - withContext(Dispatchers.Main) { - try { - v.draw(canvas) - } catch (e: Exception) { - e.log() + if (isMaskingEnabled(screenName) || (v.tag == SENSITIVE_VIEW_TAG)) { + val maskedViewsList = findViewWithTagRecursive(v, SENSITIVE_VIEW_TAG, mutableListOf()) + withContext(Dispatchers.Main) { + try { + if (maskedViewsList.isEmpty()) { + v.draw(canvas) + } else { + val alphaList = mutableListOf>() + + for (maskedView in maskedViewsList) { + alphaList.add(Pair(maskedView, maskedView.alpha)) + maskedView.alpha = 0.0f + } + + v.draw(canvas) + + for (alphaView in alphaList) { + val view = alphaView.first + view.alpha = alphaView.second + } + alphaList.clear() + } + } catch (e: Exception) { + e.log() + } + } + } else { + withContext(Dispatchers.Main) { + try { + v.draw(canvas) + } catch (e: Exception) { + e.log() + } } } insertScreenShotPathInDb(scope, context, bmp, bottomSheetFlow) @@ -65,6 +94,19 @@ suspend fun captureScreen( return bmp } +fun findViewWithTagRecursive(view: View, tag: String, maskedViews: MutableList): List { + if (view.tag == tag) { + maskedViews.add(view) + } + + if (view is ViewGroup) { + for (i in 0 until view.childCount) { + val childView = view.getChildAt(i) + findViewWithTagRecursive(childView, tag, maskedViews) + } + } + return maskedViews +} fun combineScreenshots( backgroundScreenshot: Bitmap?, @@ -74,29 +116,26 @@ fun combineScreenshots( moduleName: String? = null, scope: CoroutineScope ): Bitmap? { - if (backgroundScreenshot == null || bottomSheetScreenshot == null || isScreenDisabled( - screenName, moduleName - ) + if ( + backgroundScreenshot == null || + bottomSheetScreenshot == null || + isScreenDisabled(screenName, moduleName) ) { return null } var screenWidth = Resources.getSystem().displayMetrics.widthPixels / 2 var screenHeight = Resources.getSystem().displayMetrics.heightPixels / 2 - if (!isResolutionEven(screenWidth)) { - screenWidth += 1 - } - if (!isResolutionEven(screenHeight)) { + if (!isResolutionEven(screenWidth, screenHeight)) { screenHeight += 1 + screenWidth += 1 } val combinedBitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888) val canvas = Canvas(combinedBitmap) canvas.drawBitmap(backgroundScreenshot, 0f, 0f, null) var bottomSheetLeft = (screenWidth - bottomSheetScreenshot.width) / 2f var bottomSheetTop = screenHeight - bottomSheetScreenshot.height.toFloat() - if (!isResolutionEven(bottomSheetLeft.toInt())) { + if (!isResolutionEven(bottomSheetLeft.toInt(), bottomSheetTop.toInt())) { bottomSheetLeft = (bottomSheetLeft.toInt() + 1).toFloat() - } - if (!isResolutionEven(bottomSheetTop.toInt())) { bottomSheetTop = (bottomSheetTop.toInt() + 1).toFloat() } canvas.drawBitmap(bottomSheetScreenshot, bottomSheetLeft, bottomSheetTop, null) @@ -105,7 +144,10 @@ fun combineScreenshots( } fun insertScreenShotPathInDb( - scope: CoroutineScope, context: Context, bitmap: Bitmap?, bottomSheetFlow: Boolean? = false + scope: CoroutineScope, + context: Context, + bitmap: Bitmap?, + bottomSheetFlow: Boolean? = false ) { scope.launch(Dispatchers.IO) { try { @@ -113,23 +155,22 @@ fun insertScreenShotPathInDb( val fileName = System.currentTimeMillis().toString() + IMAGE_FILE_EXTENSION val path = fileDir.path.plus("/").plus(fileName) val imageUrl = File(path) - val fos = FileOutputStream( - imageUrl - ) - val videoQuality: Int = when (AlfredManager.config.getVideoQuality()) { - VideoQuality.HIGH.name -> { - 10 + val fos = FileOutputStream(imageUrl) + val videoQuality: Int = + when (AlfredManager.config.getVideoQuality()) { + VideoQuality.HIGH.name -> { + 10 + } + VideoQuality.LOW.name -> { + 6 + } + VideoQuality.MEDIUM.name -> { + 8 + } + else -> { + 10 + } } - VideoQuality.LOW.name -> { - 6 - } - VideoQuality.MEDIUM.name -> { - 8 - } - else -> { - 10 - } - } bitmap?.compress(CompressFormat.JPEG, videoQuality, fos) fos.flush() fos.close() @@ -138,9 +179,7 @@ fun insertScreenShotPathInDb( val screenShotDao = db.screenShotDao() try { screenShotDao.insertScreenShotPath( - ScreenShotPathHelper( - System.currentTimeMillis(), path - ) + ScreenShotPathHelper(System.currentTimeMillis(), path) ) ScreenShotStorageHelper.addImage(path) } catch (e: Exception) { @@ -149,16 +188,13 @@ fun insertScreenShotPathInDb( } } catch (e: Exception) { e.log() - } catch (e: IOException) { e.log() } } } -fun captureScreenshotOfCustomView( - view: View -): Bitmap? { +fun captureScreenshotOfCustomView(view: View): Bitmap? { view.draw(Canvas()) val bitmapForCanvas = createBitmapForView(view) try { @@ -173,10 +209,8 @@ fun createBitmapForView(view: View): Pair? { var width = view.width / 2 var height = view.height / 2 if (width > 0 && height > 0) { - if (!isResolutionEven(width)) { + if (!isResolutionEven(width, height)) { width += 1 - } - if (!isResolutionEven(height)) { height += 1 } val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) @@ -187,13 +221,11 @@ fun createBitmapForView(view: View): Pair? { return null } - fun zip(_files: ArrayList, zipFilePath: String?): Boolean? { val buffer = 1000 try { zipFilePath?.let { path -> - if (File(path).exists()) - return true + if (File(path).exists()) return true else { File(path) } @@ -235,13 +267,15 @@ fun clearScreenShot(path: List) { } fun isScreenDisabled(screenName: String? = null, moduleName: String? = null): Boolean { - if (moduleName != null && AlfredManager.config.getDisableModuleList() - ?.contains(moduleName) == true + if ( + moduleName != null && + AlfredManager.config.getDisableModuleList()?.contains(moduleName) == true ) { return true } else { - if (screenName != null && AlfredManager.config.getDisableScreenList() - ?.contains(screenName) == true + if ( + screenName != null && + AlfredManager.config.getDisableScreenList()?.contains(screenName) == true ) { return true } @@ -249,6 +283,13 @@ fun isScreenDisabled(screenName: String? = null, moduleName: String? = null): Bo return false } +fun isMaskingEnabled(screenName: String? = null): Boolean { + if (AlfredManager.config.getMaskingEnabledScreenList()?.contains(screenName) == true) { + return true + } + return false +} + fun checkFileExists(fileName: String, context: Context): File? { val file = File(context.filesDir, fileName) return if (file.exists()) { @@ -259,24 +300,26 @@ fun checkFileExists(fileName: String, context: Context): File? { } fun getTouchEvent( - currentTouchEvent: MotionEvent?, previousTouchEvent: NaviMotionEvent? + currentTouchEvent: MotionEvent?, + previousTouchEvent: NaviMotionEvent? ): Pair> { val properties = HashMap() val pointerIndex = currentTouchEvent?.actionIndex ?: 0 - val eventName = if (difference(currentTouchEvent?.getX(pointerIndex), previousTouchEvent?.positionX) && difference( - currentTouchEvent?.getY(pointerIndex), previousTouchEvent?.positionY - ) - ) { - properties[AlfredConstants.START_X] = previousTouchEvent?.positionX.toString() - properties[AlfredConstants.START_Y] = previousTouchEvent?.positionY.toString() - AlfredConstants.TOUCH_EVENT - } else { - properties[AlfredConstants.START_X] = previousTouchEvent?.positionX.toString() - properties[AlfredConstants.START_Y] = previousTouchEvent?.positionY.toString() - properties[AlfredConstants.END_X] = currentTouchEvent?.rawX.toString() - properties[AlfredConstants.END_Y] = currentTouchEvent?.rawY.toString() - AlfredConstants.SCROLL_EVENT - } + val eventName = + if ( + difference(currentTouchEvent?.getX(pointerIndex), previousTouchEvent?.positionX) && + difference(currentTouchEvent?.getY(pointerIndex), previousTouchEvent?.positionY) + ) { + properties[AlfredConstants.START_X] = previousTouchEvent?.positionX.toString() + properties[AlfredConstants.START_Y] = previousTouchEvent?.positionY.toString() + AlfredConstants.TOUCH_EVENT + } else { + properties[AlfredConstants.START_X] = previousTouchEvent?.positionX.toString() + properties[AlfredConstants.START_Y] = previousTouchEvent?.positionY.toString() + properties[AlfredConstants.END_X] = currentTouchEvent?.rawX.toString() + properties[AlfredConstants.END_Y] = currentTouchEvent?.rawY.toString() + AlfredConstants.SCROLL_EVENT + } return Pair(eventName, properties) } @@ -298,8 +341,20 @@ fun getNetworkType(context: Context): String { val mTelephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager return when (mTelephonyManager.networkType) { - TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_EDGE, TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyManager.NETWORK_TYPE_IDEN -> "2G" - TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_HSDPA, TelephonyManager.NETWORK_TYPE_HSUPA, TelephonyManager.NETWORK_TYPE_HSPA, TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyManager.NETWORK_TYPE_HSPAP -> "3G" + TelephonyManager.NETWORK_TYPE_GPRS, + TelephonyManager.NETWORK_TYPE_EDGE, + TelephonyManager.NETWORK_TYPE_CDMA, + TelephonyManager.NETWORK_TYPE_1xRTT, + TelephonyManager.NETWORK_TYPE_IDEN -> "2G" + TelephonyManager.NETWORK_TYPE_UMTS, + TelephonyManager.NETWORK_TYPE_EVDO_0, + TelephonyManager.NETWORK_TYPE_EVDO_A, + TelephonyManager.NETWORK_TYPE_HSDPA, + TelephonyManager.NETWORK_TYPE_HSUPA, + TelephonyManager.NETWORK_TYPE_HSPA, + TelephonyManager.NETWORK_TYPE_EVDO_B, + TelephonyManager.NETWORK_TYPE_EHRPD, + TelephonyManager.NETWORK_TYPE_HSPAP -> "3G" TelephonyManager.NETWORK_TYPE_LTE -> "4G" TelephonyManager.NETWORK_TYPE_NR -> "5G" else -> "Unknown" + UNDERSCORE + mTelephonyManager.networkType @@ -312,9 +367,10 @@ fun getNetworkType(context: Context): String { fun getCarrierName(context: Context): String? { return try { - (context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager).networkOperatorName + (context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager) + .networkOperatorName } catch (e: Exception) { - e.log() + e.log() null } } @@ -347,7 +403,6 @@ fun getCpuUsage(): Float { } reader.close() return cpuUsage - } fun getStorageUsage(context: Context): Pair { @@ -362,7 +417,9 @@ fun getStorageUsage(context: Context): Pair { } enum class VideoQuality { - LOW, HIGH, MEDIUM + LOW, + HIGH, + MEDIUM } private fun Any.tag(): String { @@ -386,8 +443,8 @@ fun isNetworkAvailable(context: Context): Boolean { return connectivityManager?.activeNetworkInfo?.isConnected.orFalse() } -private fun isResolutionEven(size: Int): Boolean { - return size.mod(2) == 0 +private fun isResolutionEven(width: Int, height: Int): Boolean { + return width.mod(2) == 0 && height.mod(2) == 0 } fun recordException(e: Throwable) { diff --git a/navi-alfred/src/main/java/com/navi/alfred/worker/AddEventTask.kt b/navi-alfred/src/main/java/com/navi/alfred/worker/AddEventTask.kt index 7a6947d..6748912 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/worker/AddEventTask.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/worker/AddEventTask.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2022-2023 by Navi Technologies Limited + * * Copyright © 2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -16,12 +16,11 @@ import com.navi.alfred.dispatcher.AlfredDispatcher import com.navi.alfred.utils.AlfredConstants import java.util.concurrent.atomic.AtomicInteger -class AddEventTask( - private val event: AnalyticsEvent, - private val context: Context -) : AnalyticsTask { +class AddEventTask(private val event: AnalyticsEvent, private val context: Context) : + AnalyticsTask { companion object { private var eventCount: AtomicInteger = AtomicInteger(0) + fun resetEventCount() { eventCount = AtomicInteger(0) } diff --git a/navi-alfred/src/main/java/com/navi/alfred/worker/AddMetricTask.kt b/navi-alfred/src/main/java/com/navi/alfred/worker/AddMetricTask.kt index d053682..e8c7269 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/worker/AddMetricTask.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/worker/AddMetricTask.kt @@ -1,3 +1,10 @@ +/* + * + * * Copyright © 2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + package com.navi.alfred.worker import android.content.Context @@ -9,12 +16,11 @@ import com.navi.alfred.dispatcher.AlfredDispatcher import com.navi.alfred.utils.AlfredConstants import java.util.concurrent.atomic.AtomicInteger - -class AddMetricTask( - private val event: ApiMetricHelper, private val context: Context -) : AnalyticsTask { +class AddMetricTask(private val event: ApiMetricHelper, private val context: Context) : + AnalyticsTask { companion object { private var eventCount: AtomicInteger = AtomicInteger(0) + fun resetEventCount() { eventCount = AtomicInteger(0) } diff --git a/navi-alfred/src/main/java/com/navi/alfred/worker/AnalyticsTask.kt b/navi-alfred/src/main/java/com/navi/alfred/worker/AnalyticsTask.kt index 72db335..bf8ff51 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/worker/AnalyticsTask.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/worker/AnalyticsTask.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2019-2023 by Navi Technologies Limited + * * Copyright © 2021-2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -10,8 +10,7 @@ package com.navi.alfred.worker import androidx.annotation.WorkerThread interface AnalyticsTask { - @WorkerThread - fun execute(): Boolean + @WorkerThread fun execute(): Boolean fun getTaskName(): String } diff --git a/navi-alfred/src/main/java/com/navi/alfred/worker/AnalyticsTaskProcessor.kt b/navi-alfred/src/main/java/com/navi/alfred/worker/AnalyticsTaskProcessor.kt index aaec494..5e4c3de 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/worker/AnalyticsTaskProcessor.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/worker/AnalyticsTaskProcessor.kt @@ -1,16 +1,16 @@ /* * - * * Copyright © 2019-2023 by Navi Technologies Limited + * * Copyright © 2021-2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ package com.navi.alfred.worker -import kotlinx.coroutines.asCoroutineDispatcher import java.util.concurrent.BlockingDeque import java.util.concurrent.Executors import java.util.concurrent.LinkedBlockingDeque +import kotlinx.coroutines.asCoroutineDispatcher class AnalyticsTaskProcessor { private val taskQueue: BlockingDeque = LinkedBlockingDeque() @@ -18,6 +18,7 @@ class AnalyticsTaskProcessor { private val singleThreadExecutorForSync = Executors.newSingleThreadExecutor() private var active: AnalyticsTask? = null private var isSyncEventTaskExecuted: Boolean = true + fun addTask(task: AnalyticsTask?) { if (task != null) { taskQueue.add(task) diff --git a/navi-alfred/src/main/java/com/navi/alfred/worker/UploadFileWorker.kt b/navi-alfred/src/main/java/com/navi/alfred/worker/UploadFileWorker.kt index 3ce52bb..bc78dd2 100644 --- a/navi-alfred/src/main/java/com/navi/alfred/worker/UploadFileWorker.kt +++ b/navi-alfred/src/main/java/com/navi/alfred/worker/UploadFileWorker.kt @@ -1,3 +1,10 @@ +/* + * + * * Copyright © 2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + package com.navi.alfred.worker import android.content.Context @@ -14,43 +21,53 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.lang.reflect.Type +class UploadFileWorker(context: Context, workerParams: WorkerParameters) : + CoroutineWorker(context, workerParams) { -class UploadFileWorker( - context: Context, workerParams: WorkerParameters -) : CoroutineWorker(context, workerParams) { - - override suspend fun doWork(): Result = withContext(Dispatchers.IO) { - val alfredSessionId = inputData.getString(AlfredConstants.ALFRED_SESSION_ID) - val sessionStartRecordingTime = - inputData.getLong(AlfredConstants.SESSION_START_RECORDING_TIME, 0L) - val eventStartRecordingTime = - inputData.getLong(AlfredConstants.EVENT_START_RECORDING_TIME, 0L) - val screenShotList = inputData.getString(AlfredConstants.SCREENSHOT_LIST) - val listType: Type = object : TypeToken?>() {}.type - val screenShots: List = - Gson().fromJson(screenShotList.toString(), listType) - val zipFileName = - alfredSessionId + sessionStartRecordingTime + AlfredConstants.WORKER_ZIP_FILENAME_ENDPOINT - workFailureData.add( - WorkManagerFailureInputData( - alfredSessionId = alfredSessionId, - sessionStartRecordingTime, - eventStartRecordingTime, - screenShots, - id + override suspend fun doWork(): Result = + withContext(Dispatchers.IO) { + val alfredSessionId = inputData.getString(AlfredConstants.ALFRED_SESSION_ID) + val sessionStartRecordingTime = + inputData.getLong(AlfredConstants.SESSION_START_RECORDING_TIME, 0L) + val eventStartRecordingTime = + inputData.getLong(AlfredConstants.EVENT_START_RECORDING_TIME, 0L) + val screenShotList = inputData.getString(AlfredConstants.SCREENSHOT_LIST) + val listType: Type = object : TypeToken?>() {}.type + val screenShots: List = + Gson().fromJson(screenShotList.toString(), listType) + val zipFileName = + alfredSessionId + + sessionStartRecordingTime + + AlfredConstants.WORKER_ZIP_FILENAME_ENDPOINT + workFailureData.add( + WorkManagerFailureInputData( + alfredSessionId = alfredSessionId, + sessionStartRecordingTime, + eventStartRecordingTime, + screenShots, + id + ) ) - ) - try { - if (alfredSessionId == null || sessionStartRecordingTime == 0L || eventStartRecordingTime == 0L) { - Result.failure() - } else { - AlfredManager.toZipForWorkManager(screenShots, zipFileName,sessionStartRecordingTime,alfredSessionId, eventStartRecordingTime) - Result.success() + try { + if ( + alfredSessionId == null || + sessionStartRecordingTime == 0L || + eventStartRecordingTime == 0L + ) { + Result.failure() + } else { + AlfredManager.toZipForWorkManager( + screenShots, + zipFileName, + sessionStartRecordingTime, + alfredSessionId, + eventStartRecordingTime + ) + Result.success() + } + } catch (e: Exception) { + e.printStackTrace() + Result.retry() } - } catch (e: Exception) { - e.printStackTrace() - Result.retry() } - } } -