1 /* 2 * Copyright (C) 2019 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.car.settings.datausage; 18 19 import android.content.Context; 20 import android.net.NetworkPolicy; 21 import android.net.NetworkPolicyManager; 22 import android.net.NetworkTemplate; 23 import android.os.Bundle; 24 import android.telephony.SubscriptionManager; 25 import android.telephony.TelephonyManager; 26 import android.text.format.DateUtils; 27 import android.util.Pair; 28 29 import androidx.annotation.VisibleForTesting; 30 import androidx.annotation.XmlRes; 31 import androidx.loader.app.LoaderManager; 32 33 import com.android.car.settings.R; 34 import com.android.car.settings.common.Logger; 35 import com.android.car.settings.common.SettingsFragment; 36 import com.android.settingslib.NetworkPolicyEditor; 37 38 import java.time.ZonedDateTime; 39 import java.util.Iterator; 40 41 /** 42 * Screen to display list of applications using the data. 43 */ 44 public class AppDataUsageFragment extends SettingsFragment { 45 46 private static final Logger LOG = new Logger(AppDataUsageFragment.class); 47 48 private static final String ARG_NETWORK_SUB_ID = "network_sub_id"; 49 /** Value to represent that the subscription id hasn't been computed yet. */ 50 private static final int SUB_ID_NULL = Integer.MIN_VALUE; 51 52 private AppsNetworkStatsManager mAppsNetworkStatsManager; 53 private NetworkPolicyEditor mPolicyEditor; 54 private NetworkTemplate mNetworkTemplate; 55 56 private Bundle mBundle; 57 58 /** 59 * Creates a new instance of the {@link AppDataUsageFragment}, which shows settings related to 60 * the given {@code subId}. 61 */ newInstance(int subId)62 public static AppDataUsageFragment newInstance(int subId) { 63 AppDataUsageFragment fragment = new AppDataUsageFragment(); 64 Bundle args = new Bundle(); 65 args.putInt(ARG_NETWORK_SUB_ID, subId); 66 fragment.setArguments(args); 67 return fragment; 68 } 69 70 @Override 71 @XmlRes getPreferenceScreenResId()72 protected int getPreferenceScreenResId() { 73 return R.xml.app_data_usage_fragment; 74 } 75 76 @Override onAttach(Context context)77 public void onAttach(Context context) { 78 super.onAttach(context); 79 80 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 81 int subId = getArguments() != null 82 ? getArguments().getInt(ARG_NETWORK_SUB_ID, SUB_ID_NULL) : SUB_ID_NULL; 83 if (subId == SUB_ID_NULL) { 84 LOG.d("Cannot get the subscription id from arguments. Switching to default " 85 + "subscription Id: " + subId); 86 SubscriptionManager subscriptionManager = context.getSystemService( 87 SubscriptionManager.class); 88 subId = DataUsageUtils.getDefaultSubscriptionId(subscriptionManager); 89 } 90 mNetworkTemplate = DataUsageUtils.getMobileNetworkTemplate(telephonyManager, subId); 91 mPolicyEditor = getNetworkPolicyEditor(context); 92 mAppsNetworkStatsManager = new AppsNetworkStatsManager(getContext()); 93 mAppsNetworkStatsManager.registerListener( 94 use(AppDataUsagePreferenceController.class, R.string.pk_app_data_usage_detail)); 95 } 96 97 @Override onCreate(Bundle savedInstanceState)98 public void onCreate(Bundle savedInstanceState) { 99 super.onCreate(savedInstanceState); 100 mBundle = getBundleForNetworkStats(); 101 102 LoaderManager loaderManager = LoaderManager.getInstance(this); 103 mAppsNetworkStatsManager.startLoading(loaderManager, mBundle); 104 } 105 getBundleForNetworkStats()106 private Bundle getBundleForNetworkStats() { 107 long historyStart = System.currentTimeMillis(); 108 long historyEnd = historyStart + 1; 109 110 long start = 0; 111 long end = 0; 112 113 boolean hasCycles = false; 114 115 NetworkPolicy policy = mPolicyEditor.getPolicy(mNetworkTemplate); 116 if (policy != null) { 117 Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = getCycleIterator(policy); 118 while (it.hasNext()) { 119 Pair<ZonedDateTime, ZonedDateTime> cycle = it.next(); 120 start = cycle.first.toInstant().toEpochMilli(); 121 end = cycle.second.toInstant().toEpochMilli(); 122 hasCycles = true; 123 } 124 } 125 126 if (!hasCycles) { 127 // no policy defined cycles; show entry for each four-week period 128 long cycleEnd = historyEnd; 129 while (cycleEnd > historyStart) { 130 long cycleStart = cycleEnd - (DateUtils.WEEK_IN_MILLIS * 4); 131 132 start = cycleStart; 133 end = cycleEnd; 134 cycleEnd = cycleStart; 135 } 136 } 137 138 return SummaryForAllUidLoader.buildArgs(mNetworkTemplate, start, end); 139 } 140 141 @VisibleForTesting(otherwise = VisibleForTesting.NONE) getBundle()142 Bundle getBundle() { 143 return mBundle; 144 } 145 146 @VisibleForTesting getNetworkPolicyEditor(Context context)147 NetworkPolicyEditor getNetworkPolicyEditor(Context context) { 148 return new NetworkPolicyEditor(NetworkPolicyManager.from(context)); 149 } 150 151 @VisibleForTesting getCycleIterator(NetworkPolicy policy)152 Iterator<Pair<ZonedDateTime, ZonedDateTime>> getCycleIterator(NetworkPolicy policy) { 153 return NetworkPolicyManager.cycleIterator(policy); 154 } 155 } 156