• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.settings.network.telephony;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.net.NetworkTemplate;
22 import android.provider.Settings;
23 import android.telephony.SubscriptionManager;
24 import android.text.TextUtils;
25 import android.util.Log;
26 
27 import androidx.preference.Preference;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 import com.android.settings.R;
31 import com.android.settings.datausage.DataUsageUtils;
32 import com.android.settings.datausage.lib.DataUsageLib;
33 import com.android.settingslib.net.DataUsageController;
34 import com.android.settingslib.utils.ThreadUtils;
35 
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.atomic.AtomicReference;
39 
40 /**
41  * Preference controller for "Data usage"
42  */
43 public class DataUsagePreferenceController extends TelephonyBasePreferenceController {
44 
45     private static final String LOG_TAG = "DataUsagePreferCtrl";
46 
47     private Future<NetworkTemplate> mTemplateFuture;
48     private AtomicReference<NetworkTemplate> mTemplate;
49     private Future<Long> mHistoricalUsageLevel;
50 
DataUsagePreferenceController(Context context, String key)51     public DataUsagePreferenceController(Context context, String key) {
52         super(context, key);
53         mTemplate = new AtomicReference<NetworkTemplate>();
54     }
55 
56     @Override
getAvailabilityStatus(int subId)57     public int getAvailabilityStatus(int subId) {
58         return (SubscriptionManager.isValidSubscriptionId(subId))
59                 && DataUsageUtils.hasMobileData(mContext)
60                 ? AVAILABLE
61                 : AVAILABLE_UNSEARCHABLE;
62     }
63 
64     @Override
handlePreferenceTreeClick(Preference preference)65     public boolean handlePreferenceTreeClick(Preference preference) {
66         if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
67             return false;
68         }
69         final Intent intent = new Intent(Settings.ACTION_MOBILE_DATA_USAGE);
70         intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, getNetworkTemplate());
71         intent.putExtra(Settings.EXTRA_SUB_ID, mSubId);
72 
73         mContext.startActivity(intent);
74         return true;
75     }
76 
77     @Override
updateState(Preference preference)78     public void updateState(Preference preference) {
79         super.updateState(preference);
80         if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
81             preference.setEnabled(false);
82             return;
83         }
84         final CharSequence summary = getDataUsageSummary(mContext, mSubId);
85         if (summary == null) {
86             preference.setEnabled(false);
87         } else {
88             preference.setEnabled(true);
89             preference.setSummary(summary);
90         }
91     }
92 
init(int subId)93     public void init(int subId) {
94         mSubId = subId;
95         mTemplate.set(null);
96         mTemplateFuture = ThreadUtils.postOnBackgroundThread(()
97                 -> fetchMobileTemplate(mContext, mSubId));
98     }
99 
fetchMobileTemplate(Context context, int subId)100     private NetworkTemplate fetchMobileTemplate(Context context, int subId) {
101         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
102             return null;
103         }
104         return DataUsageLib.getMobileTemplate(context, subId);
105     }
106 
getNetworkTemplate()107     private NetworkTemplate getNetworkTemplate() {
108         if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
109             return null;
110         }
111         NetworkTemplate template = mTemplate.get();
112         if (template != null) {
113             return template;
114         }
115         try {
116             template = mTemplateFuture.get();
117             mTemplate.set(template);
118         } catch (ExecutionException | InterruptedException | NullPointerException exception) {
119             Log.e(LOG_TAG, "Fail to get data usage template", exception);
120         }
121         return template;
122     }
123 
124     @VisibleForTesting
getDataUsageInfo(DataUsageController controller)125     DataUsageController.DataUsageInfo getDataUsageInfo(DataUsageController controller) {
126         return controller.getDataUsageInfo(getNetworkTemplate());
127     }
128 
getDataUsageSummary(Context context, int subId)129     private CharSequence getDataUsageSummary(Context context, int subId) {
130         final DataUsageController controller = new DataUsageController(context);
131         controller.setSubscriptionId(subId);
132 
133         mHistoricalUsageLevel = ThreadUtils.postOnBackgroundThread(() ->
134                 controller.getHistoricalUsageLevel(getNetworkTemplate()));
135 
136         final DataUsageController.DataUsageInfo usageInfo = getDataUsageInfo(controller);
137 
138         long usageLevel = usageInfo.usageLevel;
139         if (usageLevel <= 0L) {
140             try {
141                 usageLevel = mHistoricalUsageLevel.get();
142             } catch (Exception exception) {
143             }
144         }
145         if (usageLevel <= 0L) {
146             return null;
147         }
148         return context.getString(R.string.data_usage_template,
149                 DataUsageUtils.formatDataUsage(context, usageLevel), usageInfo.period);
150     }
151 }
152