• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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.development.domain.interactor
18 
19 import android.content.ClipData
20 import android.content.ClipboardManager
21 import android.content.res.Resources
22 import android.os.Build
23 import android.os.UserHandle
24 import com.android.internal.R as InternalR
25 import com.android.systemui.dagger.SysUISingleton
26 import com.android.systemui.dagger.qualifiers.Application
27 import com.android.systemui.dagger.qualifiers.Background
28 import com.android.systemui.dagger.qualifiers.Main
29 import com.android.systemui.development.data.repository.DevelopmentSettingRepository
30 import com.android.systemui.development.shared.model.BuildNumber
31 import com.android.systemui.res.R as SystemUIR
32 import com.android.systemui.user.data.repository.UserRepository
33 import com.android.systemui.user.utils.UserScopedService
34 import javax.inject.Inject
35 import kotlinx.coroutines.CoroutineDispatcher
36 import kotlinx.coroutines.CoroutineScope
37 import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
38 import kotlinx.coroutines.flow.StateFlow
39 import kotlinx.coroutines.flow.flatMapConcat
40 import kotlinx.coroutines.flow.map
41 import kotlinx.coroutines.flow.stateIn
42 import kotlinx.coroutines.withContext
43 
44 @SysUISingleton
45 class BuildNumberInteractor
46 @Inject
47 constructor(
48     repository: DevelopmentSettingRepository,
49     @Main resources: Resources,
50     private val userRepository: UserRepository,
51     private val clipboardManagerProvider: UserScopedService<ClipboardManager>,
52     @Background private val backgroundDispatcher: CoroutineDispatcher,
53     @Application private val applicationScope: CoroutineScope,
54 ) {
55 
56     /**
57      * Build number, or `null` if Development Settings is not enabled for the current user.
58      *
59      * @see DevelopmentSettingRepository.isDevelopmentSettingEnabled
60      */
61     val buildNumber: StateFlow<BuildNumber?> =
62         userRepository.selectedUserInfo
63             .flatMapConcat { userInfo -> repository.isDevelopmentSettingEnabled(userInfo) }
64             .map { enabled -> buildText.takeIf { enabled } }
65             .stateIn(applicationScope, WhileSubscribed(), null)
66 
67     private val buildText =
68         BuildNumber(
69             resources.getString(
70                 InternalR.string.bugreport_status,
71                 Build.VERSION.RELEASE_OR_CODENAME,
72                 Build.ID,
73             )
74         )
75 
76     private val clipLabel = resources.getString(SystemUIR.string.build_number_clip_data_label)
77 
78     private val currentUserHandle: UserHandle
79         get() = userRepository.getSelectedUserInfo().userHandle
80 
81     /**
82      * Copy to the clipboard the build number for the current user.
83      *
84      * This can be performed regardless of the current user having Development Settings enabled
85      */
86     suspend fun copyBuildNumber() {
87         withContext(backgroundDispatcher) {
88             clipboardManagerProvider
89                 .forUser(currentUserHandle)
90                 .setPrimaryClip(ClipData.newPlainText(clipLabel, buildText.value))
91         }
92     }
93 }
94