• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.recordissue
18 
19 import android.content.Context
20 import android.net.Uri
21 import android.os.SystemClock
22 import android.util.Log
23 import android.util.SparseArray
24 import androidx.annotation.VisibleForTesting
25 import androidx.core.content.FileProvider
26 import com.android.systemui.dagger.SysUISingleton
27 import com.android.systemui.settings.UserTracker
28 import java.io.File
29 import java.util.concurrent.TimeUnit
30 import javax.inject.Inject
31 import org.json.JSONObject
32 
33 private const val TAG = "ScreenRecordingStartTimeStore"
34 @VisibleForTesting const val REAL_TO_ELAPSED_TIME_OFFSET_NANOS_KEY = "realToElapsedTimeOffsetNanos"
35 @VisibleForTesting const val ELAPSED_REAL_TIME_NANOS_KEY = "elapsedRealTimeNanos"
36 private const val RECORDING_METADATA_FILE_SUFFIX = "screen_recording_metadata.json"
37 private const val AUTHORITY = "com.android.systemui.fileprovider"
38 
39 @SysUISingleton
40 class ScreenRecordingStartTimeStore @Inject constructor(private val userTracker: UserTracker) {
41     @VisibleForTesting val userIdToScreenRecordingStartTime = SparseArray<JSONObject>()
42 
markStartTimenull43     fun markStartTime() {
44         val elapsedRealTimeNano = SystemClock.elapsedRealtimeNanos()
45         val realToElapsedTimeOffsetNano =
46             TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis()) -
47                 SystemClock.elapsedRealtimeNanos()
48         val startTimeMetadata =
49             JSONObject()
50                 .put(ELAPSED_REAL_TIME_NANOS_KEY, elapsedRealTimeNano)
51                 .put(REAL_TO_ELAPSED_TIME_OFFSET_NANOS_KEY, realToElapsedTimeOffsetNano)
52         userIdToScreenRecordingStartTime.put(userTracker.userId, startTimeMetadata)
53     }
54 
55     /**
56      * Outputs start time metadata as Json to a file that can then be shared. Returns the Uri or
57      * null if the file system is not usable and the start time meta data is available. Uses
58      * com.android.systemui.fileprovider's authority.
59      *
60      * Because this file is not uniquely named, it doesn't need to be cleaned up. Every time it is
61      * outputted, it will overwrite the last file's contents. This is a feature, not a bug.
62      */
getFileUrinull63     fun getFileUri(context: Context): Uri? {
64         val dir = context.externalCacheDir?.apply { mkdirs() } ?: return null
65         try {
66             val outFile =
67                 File(dir, RECORDING_METADATA_FILE_SUFFIX).apply {
68                     userIdToScreenRecordingStartTime.get(userTracker.userId)?.let {
69                         writeText(it.toString())
70                     } ?: return null
71                 }
72             return FileProvider.getUriForFile(context, AUTHORITY, outFile)
73         } catch (e: Exception) {
74             Log.e(TAG, "failed to get screen recording start time metadata via file uri", e)
75             return null
76         }
77     }
78 }
79