NetworkPolicyManagerService.java revision 21c9c45e5caf62b935354b74392fb40c4bf18529
1d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/*
2d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project
3d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *
4d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * you may not use this file except in compliance with the License.
6d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * You may obtain a copy of the License at
7d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *
8d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *
10d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * See the License for the specific language governing permissions and
14d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * limitations under the License.
15d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */
16d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
17d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeypackage com.android.server.net;
18d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.CONNECTIVITY_INTERNAL;
201b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.Manifest.permission.DUMP;
21d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport static android.Manifest.permission.MANAGE_APP_TOKENS;
2221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.MANAGE_NETWORK_POLICY;
2321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
24d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_NONE;
25c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND;
26c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
27c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
281b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpPolicy;
291b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpRules;
3021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.text.format.DateUtils.DAY_IN_MILLIS;
3121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.text.format.Time.MONTH_DAY;
3221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull;
3321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
3421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.START_TAG;
35d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
36a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IActivityManager;
37a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IProcessObserver;
38a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.BroadcastReceiver;
39d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.content.Context;
40a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.Intent;
41a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.IntentFilter;
42c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.ConnectivityManager;
4321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.IConnectivityManager;
44c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.INetworkPolicyListener;
45d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.net.INetworkPolicyManager;
4675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.INetworkStatsService;
4721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkPolicy;
4821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkState;
4921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkStats;
5021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Environment;
5121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Handler;
5221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.HandlerThread;
53a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.IPowerManager;
54c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.os.RemoteCallbackList;
55a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.RemoteException;
5621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.text.format.Time;
5721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.NtpTrustedTime;
58a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.util.Slog;
59d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseArray;
60d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseBooleanArray;
61d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseIntArray;
6221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.TrustedTime;
6321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.Xml;
64d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
6521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.os.AtomicFile;
6621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.util.FastXmlSerializer;
6721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.util.Objects;
6821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.google.android.collect.Lists;
6921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.google.android.collect.Maps;
7021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
7121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParser;
7221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParserException;
7321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer;
7421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
7521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.File;
761b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.FileDescriptor;
7721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileInputStream;
7821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileNotFoundException;
7921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileOutputStream;
8021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.IOException;
811b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.PrintWriter;
8221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.net.ProtocolException;
8321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.ArrayList;
8421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.Arrays;
8521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.HashMap;
8621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
8721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport libcore.io.IoUtils;
881b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
89d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/**
90d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Service that maintains low-level network policy rules and collects usage
91d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * statistics to drive those rules.
92c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * <p>
93c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * Derives active rules by combining a given policy with other system status,
94c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * and delivers to listeners, such as {@link ConnectivityManager}, for
95c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * enforcement.
96d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */
97d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeypublic class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
98d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    private static final String TAG = "NetworkPolicy";
99d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    private static final boolean LOGD = true;
100d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
10121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final int VERSION_CURRENT = 1;
10221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
10321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_POLICY_LIST = "policy-list";
10421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_NETWORK_POLICY = "network-policy";
10521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_UID_POLICY = "uid-policy";
10621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
10721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_VERSION = "version";
10821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
10921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
11021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_CYCLE_DAY = "cycleDay";
11121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_WARNING_BYTES = "warningBytes";
11221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_LIMIT_BYTES = "limitBytes";
11321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_UID = "uid";
11421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_POLICY = "policy";
11521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
11621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
11721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
11875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Context mContext;
11975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IActivityManager mActivityManager;
12075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IPowerManager mPowerManager;
12175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final INetworkStatsService mNetworkStats;
12221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final TrustedTime mTime;
12321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
12421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private IConnectivityManager mConnManager;
125a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
12675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Object mRulesLock = new Object();
127a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
128c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private boolean mScreenOn;
129d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
130d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    /** Current network policy for each UID. */
131a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseIntArray mUidPolicy = new SparseIntArray();
132c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    /** Current derived network rules for each UID. */
133c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private SparseIntArray mUidRules = new SparseIntArray();
134d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
13521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /** Set of policies for strong network templates. */
13621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private HashMap<StrongTemplate, NetworkPolicy> mTemplatePolicy = Maps.newHashMap();
13721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
138d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    /** Foreground at both UID and PID granularity. */
139a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseBooleanArray mUidForeground = new SparseBooleanArray();
140a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
141a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            SparseBooleanArray>();
142d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
143c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
144c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            INetworkPolicyListener>();
145c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
14621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final HandlerThread mHandlerThread;
14721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final Handler mHandler;
14821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
14921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final AtomicFile mPolicyFile;
150d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
151c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    // TODO: keep whitelist of system-critical services that should never have
152c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    // rules enforced, such as system, phone, and radio UIDs.
153c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
154d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    // TODO: dispatch callbacks through handler when locked
155d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
15675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
15775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            IPowerManager powerManager, INetworkStatsService networkStats) {
15821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // TODO: move to using cached NtpTrustedTime
15921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        this(context, activityManager, powerManager, networkStats, new NtpTrustedTime(),
16021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                getSystemDir());
16121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
16221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
16321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static File getSystemDir() {
16421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        return new File(Environment.getDataDirectory(), "system");
16521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
16621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
16721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
16821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            IPowerManager powerManager, INetworkStatsService networkStats, TrustedTime time,
16921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            File systemDir) {
170a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mContext = checkNotNull(context, "missing context");
171a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mActivityManager = checkNotNull(activityManager, "missing activityManager");
172a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mPowerManager = checkNotNull(powerManager, "missing powerManager");
17375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mNetworkStats = checkNotNull(networkStats, "missing networkStats");
17421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mTime = checkNotNull(time, "missing TrustedTime");
17521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
17621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mHandlerThread = new HandlerThread(TAG);
17721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mHandlerThread.start();
17821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mHandler = new Handler(mHandlerThread.getLooper());
17921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
18021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
18121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
18221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
18321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public void bindConnectivityManager(IConnectivityManager connManager) {
18421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
185a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
186d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
187a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    public void systemReady() {
18821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
18921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // read policy from disk
19021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            readPolicyLocked();
19121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
192d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
193a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        updateScreenOn();
194d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
195a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        try {
196a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            mActivityManager.registerProcessObserver(mProcessObserver);
197a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        } catch (RemoteException e) {
198a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // ouch, no foregroundActivities updates means some processes may
199a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // never get network access.
200a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            Slog.e(TAG, "unable to register IProcessObserver", e);
201a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
202d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
203a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // TODO: traverse existing processes to know foreground state, or have
204a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // activitymanager dispatch current state when new observer attached.
205d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
206a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        final IntentFilter screenFilter = new IntentFilter();
207a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
208a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
209a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mContext.registerReceiver(mScreenReceiver, screenFilter);
210d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
21121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // watch for network interfaces to be claimed
21221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final IntentFilter ifaceFilter = new IntentFilter();
21321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        ifaceFilter.addAction(CONNECTIVITY_ACTION);
21421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.registerReceiver(mIfaceReceiver, ifaceFilter, CONNECTIVITY_INTERNAL, mHandler);
21521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
216a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
217d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
218a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
219a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
220a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
221a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // only someone like AMS should only be calling us
22275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
223a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
224a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
225a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // because a uid can have multiple pids running inside, we need to
226a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // remember all pid states and summarize foreground at uid level.
227a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
228a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // record foreground for this specific pid
229a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
230a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                if (pidForeground == null) {
231a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    pidForeground = new SparseBooleanArray(2);
232a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    mUidPidForeground.put(uid, pidForeground);
233a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                }
234a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                pidForeground.put(pid, foregroundActivities);
23521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                computeUidForegroundLocked(uid);
236a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
237d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
238d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
239a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
240a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onProcessDied(int pid, int uid) {
241a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // only someone like AMS should only be calling us
24275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
243a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
244a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
245a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // clear records and recompute, when they exist
246a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
247a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                if (pidForeground != null) {
248a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    pidForeground.delete(pid);
24921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    computeUidForegroundLocked(uid);
250a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                }
251a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
252a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
253a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    };
254a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
255a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
256a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
257a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onReceive(Context context, Intent intent) {
258a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
259a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // screen-related broadcasts are protected by system, no need
260a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // for permissions check.
261a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                updateScreenOn();
262a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
263a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
264a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    };
265d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
26621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /**
26721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * Receiver that watches for {@link IConnectivityManager} to claim network
26821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * interfaces. Used to apply {@link NetworkPolicy} when networks match
26921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * {@link StrongTemplate}.
27021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     */
27121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private BroadcastReceiver mIfaceReceiver = new BroadcastReceiver() {
27221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        @Override
27321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public void onReceive(Context context, Intent intent) {
27421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
27521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // permission above.
27621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            synchronized (mRulesLock) {
27721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                updateIfacesLocked();
27821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
27921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
28021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    };
28121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
28221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /**
28321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * Examine all connected {@link NetworkState}, looking for
28421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * {@link NetworkPolicy} that need to be enforced. When matches found, set
28521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * remaining quota based on usage cycle and historical stats.
28621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     */
28721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void updateIfacesLocked() {
28821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        if (LOGD) Slog.v(TAG, "updateIfacesLocked()");
28921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
29021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final NetworkState[] states;
29121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
29221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            states = mConnManager.getAllNetworkState();
29321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (RemoteException e) {
29421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            Slog.w(TAG, "problem reading network state");
29521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return;
29621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
29721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
29821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // first, derive identity for all connected networks, which can be used
29921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // to match against templates.
30021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final HashMap<NetworkIdentity, String> networks = Maps.newHashMap();
30121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        for (NetworkState state : states) {
30221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // stash identity and iface away for later use
30321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (state.networkInfo.isConnected()) {
30421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final String iface = state.linkProperties.getInterfaceName();
30521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
30621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                networks.put(ident, iface);
30721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
30821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
30921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
31021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // build list of rules and ifaces to enforce them against
31121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final HashMap<StrongTemplate, String[]> rules = Maps.newHashMap();
31221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final ArrayList<String> ifaceList = Lists.newArrayList();
31321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        for (StrongTemplate template : mTemplatePolicy.keySet()) {
31421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
31521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // collect all active ifaces that match this template
31621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            ifaceList.clear();
31721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            for (NetworkIdentity ident : networks.keySet()) {
31821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                if (ident.matchesTemplate(template.networkTemplate, template.subscriberId)) {
31921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    final String iface = networks.get(ident);
32021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    ifaceList.add(iface);
32121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
32221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
32321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
32421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (ifaceList.size() > 0) {
32521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
32621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                rules.put(template, ifaces);
32721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
32821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
32921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
33021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // try refreshing time source when stale
33121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
33221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            mTime.forceRefresh();
33321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
33421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
33521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
33621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                : System.currentTimeMillis();
33721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
33821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // apply each policy that we found ifaces for; compute remaining data
33921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // based on current cycle and historical stats, and push to kernel.
34021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        for (StrongTemplate template : rules.keySet()) {
34121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final NetworkPolicy policy = mTemplatePolicy.get(template);
34221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final String[] ifaces = rules.get(policy);
34321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
34421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final long start = computeLastCycleBoundary(currentTime, policy);
34521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final long end = currentTime;
34621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
34721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final NetworkStats stats;
34821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            try {
34921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                stats = mNetworkStats.getSummaryForNetwork(
35021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        start, end, template.networkTemplate, template.subscriberId);
35121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            } catch (RemoteException e) {
35221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                Slog.w(TAG, "problem reading summary for template " + template.networkTemplate);
35321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                continue;
35421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
35521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
35621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // remaining "quota" is based on usage in current cycle
35721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final long total = stats.rx[0] + stats.tx[0];
35821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final long quota = Math.max(0, policy.limitBytes - total);
35921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
36021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (LOGD) {
36121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
36221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        + Arrays.toString(ifaces) + " with quota " + quota);
36321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
36421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
36521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // TODO: push rule down through NetworkManagementService.setInterfaceQuota()
36621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
36721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
36821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
36921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
37021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /**
37121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * Compute the last cycle boundary for the given {@link NetworkPolicy}. For
37221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * example, if cycle day is 20th, and today is June 15th, it will return May
37321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * 20th. When cycle day doesn't exist in current month, it snaps to the 1st
37421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * of following month.
37521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     */
37621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    // @VisibleForTesting
37721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) {
37821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final Time now = new Time(Time.TIMEZONE_UTC);
37921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        now.set(currentTime);
38021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
38121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // first, find cycle boundary for current month
38221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final Time cycle = new Time(now);
38321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        cycle.hour = cycle.minute = cycle.second = 0;
38421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        snapToCycleDay(cycle, policy.cycleDay);
38521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
38621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        if (cycle.after(now)) {
38721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // cycle boundary is beyond now, use last cycle boundary; start by
38821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // pushing ourselves squarely into last month.
38921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final Time lastMonth = new Time(now);
39021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            lastMonth.hour = lastMonth.minute = lastMonth.second = 0;
39121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            lastMonth.monthDay = 1;
39221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            lastMonth.month -= 1;
39321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            lastMonth.normalize(true);
39421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
39521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            cycle.set(lastMonth);
39621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            snapToCycleDay(cycle, policy.cycleDay);
39721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
39821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
39921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        return cycle.toMillis(true);
40021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
40121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
40221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /**
40321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * Snap to the cycle day for the current month given; when cycle day doesn't
40421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * exist, it snaps to 1st of following month.
40521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     */
40621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static void snapToCycleDay(Time time, int cycleDay) {
40721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        if (cycleDay > time.getActualMaximum(MONTH_DAY)) {
40821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // cycle day isn't valid this month; snap to 1st of next month
40921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            time.month += 1;
41021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            time.monthDay = 1;
41121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } else {
41221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            time.monthDay = cycleDay;
41321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
41421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        time.normalize(true);
41521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
41621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
41721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void readPolicyLocked() {
41821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        if (LOGD) Slog.v(TAG, "readPolicyLocked()");
41921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
42021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // clear any existing policy and read from disk
42121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mTemplatePolicy.clear();
42221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mUidPolicy.clear();
42321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
42421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        FileInputStream fis = null;
42521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
42621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fis = mPolicyFile.openRead();
42721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final XmlPullParser in = Xml.newPullParser();
42821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            in.setInput(fis, null);
42921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
43021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            int type;
43121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            int version = VERSION_CURRENT;
43221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            while ((type = in.next()) != END_DOCUMENT) {
43321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final String tag = in.getName();
43421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                if (type == START_TAG) {
43521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    if (TAG_POLICY_LIST.equals(tag)) {
43621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        version = readIntAttribute(in, ATTR_VERSION);
43721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
43821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    } else if (TAG_NETWORK_POLICY.equals(tag)) {
43921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
44021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
44121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
44221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
44321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
44421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
44521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
44621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        mTemplatePolicy.put(new StrongTemplate(networkTemplate, subscriberId),
44721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                                new NetworkPolicy(cycleDay, warningBytes, limitBytes));
44821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
44921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    } else if (TAG_UID_POLICY.equals(tag)) {
45021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int uid = readIntAttribute(in, ATTR_UID);
45121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int policy = readIntAttribute(in, ATTR_POLICY);
45221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
45321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        mUidPolicy.put(uid, policy);
45421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    }
45521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
45621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
45721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
45821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (FileNotFoundException e) {
45921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // missing policy is okay, probably first boot
46021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (IOException e) {
46121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            Slog.e(TAG, "problem reading network stats", e);
46221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (XmlPullParserException e) {
46321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            Slog.e(TAG, "problem reading network stats", e);
46421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } finally {
46521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            IoUtils.closeQuietly(fis);
46621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
46721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
46821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
46921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void writePolicyLocked() {
47021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        if (LOGD) Slog.v(TAG, "writePolicyLocked()");
47121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
47221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        FileOutputStream fos = null;
47321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
47421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fos = mPolicyFile.startWrite();
47521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
47621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            XmlSerializer out = new FastXmlSerializer();
47721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.setOutput(fos, "utf-8");
47821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.startDocument(null, true);
47921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
48021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.startTag(null, TAG_POLICY_LIST);
48121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            writeIntAttribute(out, ATTR_VERSION, VERSION_CURRENT);
48221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
48321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // write all known network policies
48421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            for (StrongTemplate template : mTemplatePolicy.keySet()) {
48521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final NetworkPolicy policy = mTemplatePolicy.get(template);
48621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
48721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.startTag(null, TAG_NETWORK_POLICY);
48821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.networkTemplate);
48921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                if (template.subscriberId != null) {
49021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    out.attribute(null, ATTR_SUBSCRIBER_ID, template.subscriberId);
49121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
49221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
49321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
49421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
49521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.endTag(null, TAG_NETWORK_POLICY);
49621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
49721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
49821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // write all known uid policies
49921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            for (int i = 0; i < mUidPolicy.size(); i++) {
50021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final int uid = mUidPolicy.keyAt(i);
50121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final int policy = mUidPolicy.valueAt(i);
50221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
50321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.startTag(null, TAG_UID_POLICY);
50421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_UID, uid);
50521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_POLICY, policy);
50621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.endTag(null, TAG_UID_POLICY);
50721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
50821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
50921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.endTag(null, TAG_POLICY_LIST);
51021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.endDocument();
51121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
51221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            mPolicyFile.finishWrite(fos);
51321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (IOException e) {
51421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (fos != null) {
51521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                mPolicyFile.failWrite(fos);
51621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
51721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
51821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
51921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
520d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    @Override
521d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    public void setUidPolicy(int uid, int policy) {
52221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
523a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
524c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        final int oldPolicy;
525a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
526c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            oldPolicy = getUidPolicy(uid);
527a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            mUidPolicy.put(uid, policy);
528c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
52921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // uid policy changed, recompute rules and persist policy.
53021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            updateRulesForUidLocked(uid);
53121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            writePolicyLocked();
53221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
533d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
534d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
535d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    @Override
536d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    public int getUidPolicy(int uid) {
53721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
53821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
539a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
540a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            return mUidPolicy.get(uid, POLICY_NONE);
541a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
542d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
543d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
544c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    @Override
545c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    public void registerListener(INetworkPolicyListener listener) {
546c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.register(listener);
547c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
548c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        synchronized (mRulesLock) {
549c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            // dispatch any existing rules to new listeners
550c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            final int size = mUidRules.size();
551c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            for (int i = 0; i < size; i++) {
552c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                final int uid = mUidRules.keyAt(i);
553c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                final int uidRules = mUidRules.valueAt(i);
554c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                if (uidRules != RULE_ALLOW_ALL) {
555c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                    try {
556c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                        listener.onRulesChanged(uid, uidRules);
557c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                    } catch (RemoteException e) {
558c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                    }
559c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                }
560c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            }
561c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        }
562c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
563c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
564c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    @Override
565c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    public void unregisterListener(INetworkPolicyListener listener) {
566c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.unregister(listener);
567c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
568c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
5691b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    @Override
57021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public void setNetworkPolicy(int networkType, String subscriberId, NetworkPolicy policy) {
57121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
57221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
57321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
57421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            mTemplatePolicy.put(new StrongTemplate(networkType, subscriberId), policy);
57521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
57621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // network policy changed, recompute template rules based on active
57721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // interfaces and persist policy.
57821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            updateIfacesLocked();
57921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            writePolicyLocked();
58021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
58121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
58221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
58321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
58421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public NetworkPolicy getNetworkPolicy(int networkType, String subscriberId) {
58521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
58621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
58721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
58821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return mTemplatePolicy.get(new StrongTemplate(networkType, subscriberId));
58921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
59021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
59121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
59221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
5931b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
59475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
5951b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
5961b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        synchronized (mRulesLock) {
59721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fout.println("Network policies:");
59821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            for (StrongTemplate template : mTemplatePolicy.keySet()) {
59921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final NetworkPolicy policy = mTemplatePolicy.get(template);
60021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                fout.print("  "); fout.println(template.toString());
60121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                fout.print("    "); fout.println(policy.toString());
60221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
60321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
6041b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            fout.println("Policy status for known UIDs:");
6051b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
6061b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            final SparseBooleanArray knownUids = new SparseBooleanArray();
6071b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidPolicy, knownUids);
6081b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidForeground, knownUids);
6091b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidRules, knownUids);
6101b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
6111b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            final int size = knownUids.size();
6121b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            for (int i = 0; i < size; i++) {
6131b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int uid = knownUids.keyAt(i);
6141b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print("  UID=");
6151b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(uid);
6161b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
6171b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" policy=");
6181b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int policyIndex = mUidPolicy.indexOfKey(uid);
6191b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (policyIndex < 0) {
6201b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
6211b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
6221b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpPolicy(fout, mUidPolicy.valueAt(policyIndex));
6231b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
6241b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
6251b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" foreground=");
6261b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
6271b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (foregroundIndex < 0) {
6281b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
6291b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
6301b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex));
6311b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
6321b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
6331b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" rules=");
6341b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int rulesIndex = mUidRules.indexOfKey(uid);
6351b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (rulesIndex < 0) {
6361b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
6371b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
6381b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpRules(fout, mUidRules.valueAt(rulesIndex));
6391b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
6401b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
6411b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.println();
6421b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            }
6431b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
6441b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
6459599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey
6469599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey    @Override
6479599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey    public boolean isUidForeground(int uid) {
6489599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        synchronized (mRulesLock) {
6499599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey            // only really in foreground when screen is also on
6509599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey            return mUidForeground.get(uid, false) && mScreenOn;
6519599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        }
652c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
653c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
654d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    /**
655d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey     * Foreground for PID changed; recompute foreground at UID level. If
65621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * changed, will trigger {@link #updateRulesForUidLocked(int)}.
657d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey     */
65821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void computeUidForegroundLocked(int uid) {
659d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
660d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
661d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        // current pid is dropping foreground; examine other pids
662d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        boolean uidForeground = false;
663d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final int size = pidForeground.size();
664d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        for (int i = 0; i < size; i++) {
665d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            if (pidForeground.valueAt(i)) {
666d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey                uidForeground = true;
667d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey                break;
668d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            }
669d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
670d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
671d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final boolean oldUidForeground = mUidForeground.get(uid, false);
672d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        if (oldUidForeground != uidForeground) {
673d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            // foreground changed, push updated rules
674d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            mUidForeground.put(uid, uidForeground);
67521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            updateRulesForUidLocked(uid);
676a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
677a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
678a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
679a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private void updateScreenOn() {
680a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
681a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            try {
682a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                mScreenOn = mPowerManager.isScreenOn();
683a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            } catch (RemoteException e) {
684a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
68521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            updateRulesForScreenLocked();
686d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
687d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
688d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
689a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    /**
690a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey     * Update rules that might be changed by {@link #mScreenOn} value.
691a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey     */
69221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void updateRulesForScreenLocked() {
693a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // only update rules for anyone with foreground activities
694a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        final int size = mUidForeground.size();
695a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        for (int i = 0; i < size; i++) {
696a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            if (mUidForeground.valueAt(i)) {
697a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                final int uid = mUidForeground.keyAt(i);
69821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                updateRulesForUidLocked(uid);
699a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
700a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
701a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
702a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
70321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void updateRulesForUidLocked(int uid) {
704d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final int uidPolicy = getUidPolicy(uid);
7059599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        final boolean uidForeground = isUidForeground(uid);
706d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
707c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // derive active rules based on policy and active state
708c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        int uidRules = RULE_ALLOW_ALL;
709c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        if (!uidForeground && (uidPolicy & POLICY_REJECT_PAID_BACKGROUND) != 0) {
710c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            // uid in background, and policy says to block paid data
711c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            uidRules = RULE_REJECT_PAID;
712d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
713d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
714c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // TODO: only dispatch when rules actually change
715c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
716c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // record rule locally to dispatch to new listeners
717c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mUidRules.put(uid, uidRules);
718c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
719c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // dispatch changed rule to existing listeners
720c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        final int length = mListeners.beginBroadcast();
721c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        for (int i = 0; i < length; i++) {
722c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
723c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            if (listener != null) {
724c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                try {
725c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                    listener.onRulesChanged(uid, uidRules);
726c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                } catch (RemoteException e) {
727c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                }
728c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            }
729d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
730c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.finishBroadcast();
731d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
732d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
7331b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
7341b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = source.size();
7351b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
7361b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            target.put(source.keyAt(i), true);
7371b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
7381b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
7391b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
7401b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) {
7411b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = source.size();
7421b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
7431b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            target.put(source.keyAt(i), true);
7441b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
7451b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
7461b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
7471b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) {
7481b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        fout.print("[");
7491b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = value.size();
7501b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
7511b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            fout.print(value.keyAt(i) + "=" + value.valueAt(i));
7521b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            if (i < size - 1) fout.print(",");
7531b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
7541b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        fout.print("]");
7551b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
75621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
75721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static int readIntAttribute(XmlPullParser in, String name) throws IOException {
75821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final String value = in.getAttributeValue(null, name);
75921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
76021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return Integer.parseInt(value);
76121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (NumberFormatException e) {
76221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
76321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
76421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
76521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
76621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static long readLongAttribute(XmlPullParser in, String name) throws IOException {
76721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final String value = in.getAttributeValue(null, name);
76821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
76921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return Long.parseLong(value);
77021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (NumberFormatException e) {
77121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
77221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
77321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
77421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
77521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static void writeIntAttribute(XmlSerializer out, String name, int value)
77621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            throws IOException {
77721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        out.attribute(null, name, Integer.toString(value));
77821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
77921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
78021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static void writeLongAttribute(XmlSerializer out, String name, long value)
78121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            throws IOException {
78221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        out.attribute(null, name, Long.toString(value));
78321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
78421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
78521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /**
78621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * Network template with strong subscriber ID, used as key when defining
78721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * {@link NetworkPolicy}.
78821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     */
78921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static class StrongTemplate {
79021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public final int networkTemplate;
79121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public final String subscriberId;
79221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
79321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public StrongTemplate(int networkTemplate, String subscriberId) {
79421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            this.networkTemplate = networkTemplate;
79521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            this.subscriberId = subscriberId;
79621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
79721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
79821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        @Override
79921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public int hashCode() {
80021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return Objects.hashCode(networkTemplate, subscriberId);
80121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
80221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
80321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        @Override
80421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public boolean equals(Object obj) {
80521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (obj instanceof StrongTemplate) {
80621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final StrongTemplate template = (StrongTemplate) obj;
80721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                return template.networkTemplate == networkTemplate
80821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        && Objects.equal(template.subscriberId, subscriberId);
80921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
81021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return false;
81121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
81221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
81321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        @Override
81421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public String toString() {
81521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return "TemplateIdentity: networkTemplate=" + networkTemplate + ", subscriberId="
81621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    + subscriberId;
81721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
81821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
81921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
82021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
821d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey}
822