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.app.IActivityManager 20 import android.app.NotificationManager 21 import android.content.Context 22 import android.content.Intent 23 import android.content.res.Resources 24 import android.net.Uri 25 import android.os.Handler 26 import android.os.UserHandle 27 import com.android.internal.logging.UiEventLogger 28 import com.android.systemui.animation.DialogTransitionAnimator 29 import com.android.systemui.dagger.qualifiers.LongRunning 30 import com.android.systemui.dagger.qualifiers.Main 31 import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor 32 import com.android.systemui.res.R 33 import com.android.systemui.screenrecord.RecordingController 34 import com.android.systemui.screenrecord.RecordingService 35 import com.android.systemui.screenrecord.RecordingServiceStrings 36 import com.android.systemui.settings.UserContextProvider 37 import com.android.systemui.statusbar.phone.KeyguardDismissUtil 38 import java.util.concurrent.Executor 39 import javax.inject.Inject 40 41 class IssueRecordingService 42 @Inject 43 constructor( 44 controller: RecordingController, 45 @LongRunning private val bgExecutor: Executor, 46 @Main handler: Handler, 47 uiEventLogger: UiEventLogger, 48 notificationManager: NotificationManager, 49 userContextProvider: UserContextProvider, 50 keyguardDismissUtil: KeyguardDismissUtil, 51 private val dialogTransitionAnimator: DialogTransitionAnimator, 52 private val panelInteractor: PanelInteractor, 53 private val traceurMessageSender: TraceurMessageSender, 54 private val issueRecordingState: IssueRecordingState, 55 private val iActivityManager: IActivityManager, 56 ) : 57 RecordingService( 58 controller, 59 bgExecutor, 60 handler, 61 uiEventLogger, 62 notificationManager, 63 userContextProvider, 64 keyguardDismissUtil 65 ) { 66 getTagnull67 override fun getTag(): String = TAG 68 69 override fun getChannelId(): String = CHANNEL_ID 70 71 override fun provideRecordingServiceStrings(): RecordingServiceStrings = IrsStrings(resources) 72 73 override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { 74 when (intent?.action) { 75 ACTION_START -> { 76 bgExecutor.execute { 77 traceurMessageSender.startTracing(issueRecordingState.traceType) 78 } 79 issueRecordingState.isRecording = true 80 if (!issueRecordingState.recordScreen) { 81 // If we don't want to record the screen, the ACTION_SHOW_START_NOTIF action 82 // will circumvent the RecordingService's screen recording start code. 83 return super.onStartCommand(Intent(ACTION_SHOW_START_NOTIF), flags, startId) 84 } 85 } 86 ACTION_STOP, 87 ACTION_STOP_NOTIF -> { 88 // ViewCapture needs to save it's data before it is disabled, or else the data will 89 // be lost. This is expected to change in the near future, and when that happens 90 // this line should be removed. 91 bgExecutor.execute { traceurMessageSender.stopTracing() } 92 issueRecordingState.isRecording = false 93 } 94 ACTION_SHARE -> { 95 bgExecutor.execute { 96 mNotificationManager.cancelAsUser( 97 null, 98 mNotificationId, 99 UserHandle(mUserContextTracker.userContext.userId) 100 ) 101 102 val screenRecording = intent.getParcelableExtra(EXTRA_PATH, Uri::class.java) 103 if (issueRecordingState.takeBugreport) { 104 iActivityManager.requestBugReportWithExtraAttachment(screenRecording) 105 } else { 106 traceurMessageSender.shareTraces(applicationContext, screenRecording) 107 } 108 } 109 110 dialogTransitionAnimator.disableAllCurrentDialogsExitAnimations() 111 panelInteractor.collapsePanels() 112 113 // Unlike all other actions, action_share has different behavior for the screen 114 // recording qs tile than it does for the record issue qs tile. Return sticky to 115 // avoid running any of the base class' code for this action. 116 return START_STICKY 117 } 118 else -> {} 119 } 120 return super.onStartCommand(intent, flags, startId) 121 } 122 123 companion object { 124 private const val TAG = "IssueRecordingService" 125 private const val CHANNEL_ID = "issue_record" 126 127 /** 128 * Get an intent to stop the issue recording service. 129 * 130 * @param context Context from the requesting activity 131 * @return 132 */ getStopIntentnull133 fun getStopIntent(context: Context): Intent = 134 Intent(context, IssueRecordingService::class.java) 135 .setAction(ACTION_STOP) 136 .putExtra(Intent.EXTRA_USER_HANDLE, context.userId) 137 138 /** 139 * Get an intent to start the issue recording service. 140 * 141 * @param context Context from the requesting activity 142 */ 143 fun getStartIntent(context: Context): Intent = 144 Intent(context, IssueRecordingService::class.java).setAction(ACTION_START) 145 } 146 } 147 148 private class IrsStrings(private val res: Resources) : RecordingServiceStrings(res) { 149 override val title 150 get() = res.getString(R.string.issuerecord_title) 151 152 override val notificationChannelDescription 153 get() = res.getString(R.string.issuerecord_channel_description) 154 155 override val startErrorResId 156 get() = R.string.issuerecord_start_error 157 158 override val startError 159 get() = res.getString(R.string.issuerecord_start_error) 160 161 override val saveErrorResId 162 get() = R.string.issuerecord_save_error 163 164 override val saveError 165 get() = res.getString(R.string.issuerecord_save_error) 166 167 override val ongoingRecording 168 get() = res.getString(R.string.issuerecord_ongoing_screen_only) 169 170 override val backgroundProcessingLabel 171 get() = res.getString(R.string.issuerecord_background_processing_label) 172 173 override val saveTitle 174 get() = res.getString(R.string.issuerecord_save_title) 175 } 176