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