1 /*
2  * Copyright (C) 2019 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.controls.management
18 
19 import android.app.ActivityOptions
20 import android.content.ComponentName
21 import android.content.Intent
22 import android.os.Bundle
23 import android.view.LayoutInflater
24 import android.view.View
25 import android.view.ViewGroup
26 import android.view.ViewStub
27 import android.widget.Button
28 import android.widget.TextView
29 import androidx.recyclerview.widget.LinearLayoutManager
30 import androidx.recyclerview.widget.RecyclerView
31 import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
32 import com.android.systemui.R
33 import com.android.systemui.broadcast.BroadcastDispatcher
34 import com.android.systemui.controls.controller.ControlsController
35 import com.android.systemui.controls.ui.ControlsActivity
36 import com.android.systemui.controls.ui.ControlsUiController
37 import com.android.systemui.dagger.qualifiers.Background
38 import com.android.systemui.dagger.qualifiers.Main
39 import com.android.systemui.settings.CurrentUserTracker
40 import com.android.systemui.util.LifecycleActivity
41 import java.util.concurrent.Executor
42 import javax.inject.Inject
43 
44 /**
45  * Activity to select an application to favorite the [Control] provided by them.
46  */
47 class ControlsProviderSelectorActivity @Inject constructor(
48     @Main private val executor: Executor,
49     @Background private val backExecutor: Executor,
50     private val listingController: ControlsListingController,
51     private val controlsController: ControlsController,
52     private val broadcastDispatcher: BroadcastDispatcher,
53     private val uiController: ControlsUiController
54 ) : LifecycleActivity() {
55 
56     companion object {
57         private const val TAG = "ControlsProviderSelectorActivity"
58         const val BACK_SHOULD_EXIT = "back_should_exit"
59     }
60     private var backShouldExit = false
61     private lateinit var recyclerView: RecyclerView
62     private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
63         private val startingUser = listingController.currentUserId
64 
65         override fun onUserSwitched(newUserId: Int) {
66             if (newUserId != startingUser) {
67                 stopTracking()
68                 finish()
69             }
70         }
71     }
72 
73     override fun onCreate(savedInstanceState: Bundle?) {
74         super.onCreate(savedInstanceState)
75 
76         setContentView(R.layout.controls_management)
77 
78         getLifecycle().addObserver(
79             ControlsAnimations.observerForAnimations(
80                 requireViewById<ViewGroup>(R.id.controls_management_root),
81                 window,
82                 intent
83             )
84         )
85 
86         requireViewById<ViewStub>(R.id.stub).apply {
87             layoutResource = R.layout.controls_management_apps
88             inflate()
89         }
90 
91         recyclerView = requireViewById(R.id.list)
92         recyclerView.layoutManager = LinearLayoutManager(applicationContext)
93 
94         requireViewById<TextView>(R.id.title).apply {
95             text = resources.getText(R.string.controls_providers_title)
96         }
97 
98         requireViewById<Button>(R.id.other_apps).apply {
99             visibility = View.VISIBLE
100             setText(com.android.internal.R.string.cancel)
101             setOnClickListener {
102                 onBackPressed()
103             }
104         }
105         requireViewById<View>(R.id.done).visibility = View.GONE
106 
107         backShouldExit = intent.getBooleanExtra(BACK_SHOULD_EXIT, false)
108     }
109 
110     override fun onBackPressed() {
111         if (!backShouldExit) {
112             val i = Intent().apply {
113                 component = ComponentName(applicationContext, ControlsActivity::class.java)
114             }
115             startActivity(i, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
116         }
117         animateExitAndFinish()
118     }
119 
120     override fun onStart() {
121         super.onStart()
122         currentUserTracker.startTracking()
123 
124         recyclerView.alpha = 0.0f
125         recyclerView.adapter = AppAdapter(
126                 backExecutor,
127                 executor,
128                 lifecycle,
129                 listingController,
130                 LayoutInflater.from(this),
131                 ::launchFavoritingActivity,
132                 FavoritesRenderer(resources, controlsController::countFavoritesForComponent),
133                 resources).apply {
134             registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
135                 var hasAnimated = false
136                 override fun onChanged() {
137                     if (!hasAnimated) {
138                         hasAnimated = true
139                         ControlsAnimations.enterAnimation(recyclerView).start()
140                     }
141                 }
142             })
143         }
144     }
145 
146     override fun onStop() {
147         super.onStop()
148         currentUserTracker.stopTracking()
149     }
150 
151     /**
152      * Launch the [ControlsFavoritingActivity] for the specified component.
153      * @param component a component name for a [ControlsProviderService]
154      */
155     fun launchFavoritingActivity(component: ComponentName?) {
156         executor.execute {
157             component?.let {
158                 val intent = Intent(applicationContext, ControlsFavoritingActivity::class.java)
159                         .apply {
160                     putExtra(ControlsFavoritingActivity.EXTRA_APP,
161                             listingController.getAppLabel(it))
162                     putExtra(Intent.EXTRA_COMPONENT_NAME, it)
163                     putExtra(ControlsFavoritingActivity.EXTRA_FROM_PROVIDER_SELECTOR, true)
164                 }
165                 startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
166                 animateExitAndFinish()
167             }
168         }
169     }
170 
171     override fun onDestroy() {
172         currentUserTracker.stopTracking()
173         super.onDestroy()
174     }
175 
176     private fun animateExitAndFinish() {
177         val rootView = requireViewById<ViewGroup>(R.id.controls_management_root)
178         ControlsAnimations.exitAnimation(
179                 rootView,
180                 object : Runnable {
181                     override fun run() {
182                         finish()
183                     }
184                 }
185         ).start()
186     }
187 }
188