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