1 /*
<lambda>null2  * Copyright (C) 2017 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 package com.android.settings.applications.specialaccess
17 
18 import android.content.Context
19 import android.net.NetworkPolicyManager
20 import android.os.UserHandle
21 import androidx.lifecycle.Lifecycle
22 import androidx.lifecycle.LifecycleOwner
23 import androidx.lifecycle.lifecycleScope
24 import androidx.lifecycle.repeatOnLifecycle
25 import androidx.preference.Preference
26 import androidx.preference.PreferenceScreen
27 import com.android.settings.R
28 import com.android.settings.core.BasePreferenceController
29 import com.android.settingslib.spa.framework.util.formatString
30 import com.android.settingslib.spaprivileged.model.app.AppListRepository
31 import com.android.settingslib.spaprivileged.model.app.AppListRepositoryImpl
32 import com.google.common.annotations.VisibleForTesting
33 import kotlinx.coroutines.Dispatchers
34 import kotlinx.coroutines.async
35 import kotlinx.coroutines.coroutineScope
36 import kotlinx.coroutines.launch
37 import kotlinx.coroutines.withContext
38 
39 class DataSaverController(context: Context, key: String) : BasePreferenceController(context, key) {
40 
41     private lateinit var preference: Preference
42 
43     @AvailabilityStatus
44     override fun getAvailabilityStatus(): Int = when {
45         mContext.resources.getBoolean(R.bool.config_show_data_saver) -> AVAILABLE
46         else -> UNSUPPORTED_ON_DEVICE
47     }
48 
49     override fun displayPreference(screen: PreferenceScreen) {
50         super.displayPreference(screen)
51         preference = screen.findPreference(preferenceKey)!!
52     }
53 
54     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
55         viewLifecycleOwner.lifecycleScope.launch {
56             viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
57                 preference.summary = getUnrestrictedSummary(mContext)
58             }
59         }
60     }
61 
62     companion object {
63         @VisibleForTesting
64         suspend fun getUnrestrictedSummary(
65             context: Context,
66             appListRepository: AppListRepository =
67                 AppListRepositoryImpl(context.applicationContext),
68         ) = context.formatString(
69             R.string.data_saver_unrestricted_summary,
70             "count" to getAllowCount(context.applicationContext, appListRepository),
71         )
72 
73         private suspend fun getAllowCount(context: Context, appListRepository: AppListRepository) =
74             withContext(Dispatchers.IO) {
75                 coroutineScope {
76                     val appsDeferred = async {
77                         appListRepository.loadAndFilterApps(
78                             userId = UserHandle.myUserId(),
79                             isSystemApp = false,
80                         )
81                     }
82                     val uidsAllowed = NetworkPolicyManager.from(context)
83                         .getUidsWithPolicy(NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND)
84                     appsDeferred.await().count { app -> app.uid in uidsAllowed }
85                 }
86             }
87     }
88 }