1 /*
2  * Copyright (C) 2022 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.screenshot.proxy
18 
19 import android.content.Intent
20 import android.os.IBinder
21 import android.os.RemoteException
22 import android.util.Log
23 import androidx.lifecycle.LifecycleService
24 import androidx.lifecycle.lifecycleScope
25 import com.android.app.tracing.coroutines.launchTraced as launch
26 import com.android.systemui.dagger.qualifiers.Main
27 import com.android.systemui.plugins.ActivityStarter
28 import com.android.systemui.shade.ShadeExpansionStateManager
29 import javax.inject.Inject
30 import kotlinx.coroutines.CoroutineDispatcher
31 import kotlinx.coroutines.withContext
32 
33 /** Provides state from the main SystemUI process on behalf of the Screenshot process. */
34 class ScreenshotProxyService
35 @Inject
36 constructor(
37     private val mExpansionMgr: ShadeExpansionStateManager,
38     @Main private val mMainDispatcher: CoroutineDispatcher,
39     private val activityStarter: ActivityStarter,
40 ) : LifecycleService() {
41 
42     private val mBinder: IBinder =
43         object : IScreenshotProxy.Stub() {
44             /** @return true when the notification shade is partially or fully expanded. */
isNotificationShadeExpandednull45             override fun isNotificationShadeExpanded(): Boolean {
46                 val expanded = !mExpansionMgr.isClosed()
47                 Log.d(TAG, "isNotificationShadeExpanded(): $expanded")
48                 return expanded
49             }
50 
dismissKeyguardnull51             override fun dismissKeyguard(callback: IOnDoneCallback) {
52                 lifecycleScope.launch("IScreenshotProxy#dismissKeyguard") {
53                     executeAfterDismissing(callback)
54                 }
55             }
56         }
57 
executeAfterDismissingnull58     private suspend fun executeAfterDismissing(callback: IOnDoneCallback) =
59         withContext(mMainDispatcher) {
60             activityStarter.executeRunnableDismissingKeyguard(
61                 {
62                     try {
63                         callback.onDone(true)
64                     } catch (e: RemoteException) {
65                         Log.w(TAG, "Failed to complete callback transaction", e)
66                     }
67                 },
68                 null,
69                 true /* dismissShade */,
70                 true /* afterKeyguardGone */,
71                 true, /* deferred */
72             )
73         }
74 
onBindnull75     override fun onBind(intent: Intent): IBinder? {
76         Log.d(TAG, "onBind: $intent")
77         return mBinder
78     }
79 
80     companion object {
81         const val TAG = "ScreenshotProxyService"
82     }
83 }
84