1 /*
2  * Copyright (C) 2011 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.settingslib.net;
18 
19 import static android.net.NetworkStats.SET_DEFAULT;
20 import static android.net.NetworkStats.SET_FOREGROUND;
21 import static android.net.NetworkStats.TAG_NONE;
22 import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
23 import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
24 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
25 
26 import android.content.AsyncTaskLoader;
27 import android.content.Context;
28 import android.net.INetworkStatsSession;
29 import android.net.NetworkStatsHistory;
30 import android.net.NetworkTemplate;
31 import android.os.Bundle;
32 import android.os.RemoteException;
33 
34 import com.android.settingslib.AppItem;
35 
36 /**
37  * Loader for historical chart data for both network and UID details.
38  */
39 public class ChartDataLoader extends AsyncTaskLoader<ChartData> {
40     private static final String KEY_TEMPLATE = "template";
41     private static final String KEY_APP = "app";
42     private static final String KEY_FIELDS = "fields";
43 
44     private final INetworkStatsSession mSession;
45     private final Bundle mArgs;
46 
buildArgs(NetworkTemplate template, AppItem app)47     public static Bundle buildArgs(NetworkTemplate template, AppItem app) {
48         return buildArgs(template, app, FIELD_RX_BYTES | FIELD_TX_BYTES);
49     }
50 
buildArgs(NetworkTemplate template, AppItem app, int fields)51     public static Bundle buildArgs(NetworkTemplate template, AppItem app, int fields) {
52         final Bundle args = new Bundle();
53         args.putParcelable(KEY_TEMPLATE, template);
54         args.putParcelable(KEY_APP, app);
55         args.putInt(KEY_FIELDS, fields);
56         return args;
57     }
58 
ChartDataLoader(Context context, INetworkStatsSession session, Bundle args)59     public ChartDataLoader(Context context, INetworkStatsSession session, Bundle args) {
60         super(context);
61         mSession = session;
62         mArgs = args;
63     }
64 
65     @Override
onStartLoading()66     protected void onStartLoading() {
67         super.onStartLoading();
68         forceLoad();
69     }
70 
71     @Override
loadInBackground()72     public ChartData loadInBackground() {
73         final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
74         final AppItem app = mArgs.getParcelable(KEY_APP);
75         final int fields = mArgs.getInt(KEY_FIELDS);
76 
77         try {
78             return loadInBackground(template, app, fields);
79         } catch (RemoteException e) {
80             // since we can't do much without history, and we don't want to
81             // leave with half-baked UI, we bail hard.
82             throw new RuntimeException("problem reading network stats", e);
83         }
84     }
85 
loadInBackground(NetworkTemplate template, AppItem app, int fields)86     private ChartData loadInBackground(NetworkTemplate template, AppItem app, int fields)
87             throws RemoteException {
88         final ChartData data = new ChartData();
89         data.network = mSession.getHistoryForNetwork(template, fields);
90 
91         if (app != null) {
92             // load stats for current uid and template
93             final int size = app.uids.size();
94             for (int i = 0; i < size; i++) {
95                 final int uid = app.uids.keyAt(i);
96                 data.detailDefault = collectHistoryForUid(
97                         template, uid, SET_DEFAULT, data.detailDefault);
98                 data.detailForeground = collectHistoryForUid(
99                         template, uid, SET_FOREGROUND, data.detailForeground);
100             }
101 
102             if (size > 0) {
103                 data.detail = new NetworkStatsHistory(data.detailForeground.getBucketDuration());
104                 data.detail.recordEntireHistory(data.detailDefault);
105                 data.detail.recordEntireHistory(data.detailForeground);
106             } else {
107                 data.detailDefault = new NetworkStatsHistory(HOUR_IN_MILLIS);
108                 data.detailForeground = new NetworkStatsHistory(HOUR_IN_MILLIS);
109                 data.detail = new NetworkStatsHistory(HOUR_IN_MILLIS);
110             }
111         }
112 
113         return data;
114     }
115 
116     @Override
onStopLoading()117     protected void onStopLoading() {
118         super.onStopLoading();
119         cancelLoad();
120     }
121 
122     @Override
onReset()123     protected void onReset() {
124         super.onReset();
125         cancelLoad();
126     }
127 
128     /**
129      * Collect {@link NetworkStatsHistory} for the requested UID, combining with
130      * an existing {@link NetworkStatsHistory} if provided.
131      */
collectHistoryForUid( NetworkTemplate template, int uid, int set, NetworkStatsHistory existing)132     private NetworkStatsHistory collectHistoryForUid(
133             NetworkTemplate template, int uid, int set, NetworkStatsHistory existing)
134             throws RemoteException {
135         final NetworkStatsHistory history = mSession.getHistoryForUid(
136                 template, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES);
137 
138         if (existing != null) {
139             existing.recordEntireHistory(history);
140             return existing;
141         } else {
142             return history;
143         }
144     }
145 }
146