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
18 
19 import android.content.ComponentName
20 import android.content.Context
21 import android.content.pm.PackageManager
22 import android.content.pm.PackageManager.ComponentInfoFlags
23 import android.graphics.drawable.Drawable
24 import android.os.UserHandle
25 import android.os.UserManager
26 import android.util.Log
27 import android.view.View
28 import android.view.ViewGroup
29 import android.widget.ImageView
30 import android.widget.TextView
31 import com.android.systemui.R
32 import javax.inject.Inject
33 
34 /**
35  * Handles work profile first run, determining whether a first run UI should be shown and populating
36  * that UI if needed.
37  */
38 class WorkProfileMessageController
39 @Inject
40 constructor(
41     private val context: Context,
42     private val userManager: UserManager,
43     private val packageManager: PackageManager,
44 ) {
45 
46     /**
47      * @return a populated WorkProfileFirstRunData object if a work profile first run message should
48      *   be shown
49      */
50     fun onScreenshotTaken(userHandle: UserHandle?): WorkProfileFirstRunData? {
51         if (userHandle == null) return null
52 
53         if (userManager.isManagedProfile(userHandle.identifier) && !messageAlreadyDismissed()) {
54             var badgedIcon: Drawable? = null
55             var label: CharSequence? = null
56             val fileManager = fileManagerComponentName()
57                 ?: return WorkProfileFirstRunData(defaultFileAppName(), null)
58             try {
59                 val info = packageManager.getActivityInfo(fileManager, ComponentInfoFlags.of(0L))
60                 val icon = packageManager.getActivityIcon(fileManager)
61                 badgedIcon = packageManager.getUserBadgedIcon(icon, userHandle)
62                 label = info.loadLabel(packageManager)
63             } catch (e: PackageManager.NameNotFoundException) {
64                 Log.w(TAG, "Component $fileManager not found")
65             }
66 
67             // If label wasn't loaded, use a default
68             return WorkProfileFirstRunData(label ?: defaultFileAppName(), badgedIcon)
69         }
70         return null
71     }
72 
73     /**
74      * Use the provided WorkProfileFirstRunData to populate the work profile first run UI in the
75      * given view.
76      */
77     fun populateView(view: ViewGroup, data: WorkProfileFirstRunData, animateOut: () -> Unit) {
78         if (data.icon != null) {
79             // Replace the default icon if one is provided.
80             val imageView: ImageView = view.requireViewById<ImageView>(R.id.screenshot_message_icon)
81             imageView.setImageDrawable(data.icon)
82         }
83         val messageContent = view.requireViewById<TextView>(R.id.screenshot_message_content)
84         messageContent.text =
85             view.context.getString(R.string.screenshot_work_profile_notification, data.appName)
86         view.requireViewById<View>(R.id.message_dismiss_button).setOnClickListener {
87             animateOut()
88             onMessageDismissed()
89         }
90     }
91 
92     private fun messageAlreadyDismissed(): Boolean {
93         return sharedPreference().getBoolean(PREFERENCE_KEY, false)
94     }
95 
96     private fun onMessageDismissed() {
97         val editor = sharedPreference().edit()
98         editor.putBoolean(PREFERENCE_KEY, true)
99         editor.apply()
100     }
101 
102     private fun sharedPreference() =
103         context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
104 
105     private fun fileManagerComponentName() =
106         ComponentName.unflattenFromString(
107             context.getString(R.string.config_sceenshotWorkProfileFilesApp)
108         )
109 
110     private fun defaultFileAppName() = context.getString(R.string.screenshot_default_files_app_name)
111 
112     data class WorkProfileFirstRunData constructor(val appName: CharSequence, val icon: Drawable?)
113 
114     companion object {
115         const val TAG = "WorkProfileMessageCtrl"
116         const val SHARED_PREFERENCES_NAME = "com.android.systemui.screenshot"
117         const val PREFERENCE_KEY = "work_profile_first_run"
118     }
119 }
120