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.mediaprojection.appselector.view
18  
19  import android.content.Context
20  import android.content.res.Configuration
21  import android.graphics.Rect
22  import android.view.WindowInsets.Type
23  import android.view.WindowManager
24  import androidx.lifecycle.DefaultLifecycleObserver
25  import androidx.lifecycle.LifecycleOwner
26  import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorScope
27  import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener
28  import com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen
29  import com.android.systemui.statusbar.policy.CallbackController
30  import com.android.systemui.statusbar.policy.ConfigurationController
31  import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
32  import javax.inject.Inject
33  
34  @MediaProjectionAppSelectorScope
35  class TaskPreviewSizeProvider
36  @Inject
37  constructor(
38      private val context: Context,
39      private val windowManager: WindowManager,
40      private val configurationController: ConfigurationController,
41  ) : CallbackController<TaskPreviewSizeListener>, ConfigurationListener, DefaultLifecycleObserver {
42  
43      /** Returns the size of the task preview on the screen in pixels */
44      val size: Rect = calculateSize()
45  
46      private val listeners = arrayListOf<TaskPreviewSizeListener>()
47  
48      override fun onCreate(owner: LifecycleOwner) {
49          configurationController.addCallback(this)
50      }
51  
52      override fun onDestroy(owner: LifecycleOwner) {
53          configurationController.removeCallback(this)
54      }
55  
56      override fun onConfigChanged(newConfig: Configuration) {
57          val newSize = calculateSize()
58          if (newSize != size) {
59              size.set(newSize)
60              listeners.forEach { it.onTaskSizeChanged(size) }
61          }
62      }
63  
64      private fun calculateSize(): Rect {
65          val windowMetrics = windowManager.maximumWindowMetrics
66          val maximumWindowHeight = windowMetrics.bounds.height()
67          val width = windowMetrics.bounds.width()
68          var height = maximumWindowHeight
69  
70          val isLargeScreen = isLargeScreen(context)
71          if (isLargeScreen) {
72              val taskbarSize =
73                  windowManager.currentWindowMetrics.windowInsets
74                      .getInsets(Type.tappableElement())
75                      .bottom
76              height -= taskbarSize
77          }
78  
79          val previewSize = Rect(0, 0, width, height)
80          val scale = (height / maximumWindowHeight.toFloat()) / SCREEN_HEIGHT_TO_TASK_HEIGHT_RATIO
81          previewSize.scale(scale)
82  
83          return previewSize
84      }
85  
86      override fun addCallback(listener: TaskPreviewSizeListener) {
87          listeners += listener
88      }
89  
90      override fun removeCallback(listener: TaskPreviewSizeListener) {
91          listeners -= listener
92      }
93  
94      interface TaskPreviewSizeListener {
95          fun onTaskSizeChanged(size: Rect)
96      }
97  }
98  
99  /**
100   * How many times smaller the task preview should be on the screen comparing to the height of the
101   * screen
102   */
103  private const val SCREEN_HEIGHT_TO_TASK_HEIGHT_RATIO = 4f
104