NetworkPolicyManagerService.java revision 9599cc5f21152860af9d18015b1398b50743da76
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
191b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.Manifest.permission.DUMP;
20d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport static android.Manifest.permission.MANAGE_APP_TOKENS;
21d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport static android.Manifest.permission.UPDATE_DEVICE_STATS;
22d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_NONE;
23c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND;
24c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
25c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
261b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpPolicy;
271b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpRules;
28d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
29a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IActivityManager;
30a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IProcessObserver;
31a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.BroadcastReceiver;
32d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.content.Context;
33a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.Intent;
34a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.IntentFilter;
35c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.ConnectivityManager;
36c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.INetworkPolicyListener;
37d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.net.INetworkPolicyManager;
38a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.IPowerManager;
39c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.os.RemoteCallbackList;
40a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.RemoteException;
41d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.Log;
42a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.util.Slog;
43d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseArray;
44d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseBooleanArray;
45d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseIntArray;
46d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
471b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.FileDescriptor;
481b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.PrintWriter;
491b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
50d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/**
51d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Service that maintains low-level network policy rules and collects usage
52d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * statistics to drive those rules.
53c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * <p>
54c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * Derives active rules by combining a given policy with other system status,
55c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * and delivers to listeners, such as {@link ConnectivityManager}, for
56c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * enforcement.
57d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */
58d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeypublic class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
59d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    private static final String TAG = "NetworkPolicy";
60d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    private static final boolean LOGD = true;
61d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
62d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    private Context mContext;
63a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private IActivityManager mActivityManager;
64a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private IPowerManager mPowerManager;
65a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
66a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private Object mRulesLock = new Object();
67a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
68c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private boolean mScreenOn;
69d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
70d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    /** Current network policy for each UID. */
71a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseIntArray mUidPolicy = new SparseIntArray();
72c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    /** Current derived network rules for each UID. */
73c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private SparseIntArray mUidRules = new SparseIntArray();
74d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
75d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    /** Foreground at both UID and PID granularity. */
76a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseBooleanArray mUidForeground = new SparseBooleanArray();
77a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
78a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            SparseBooleanArray>();
79d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
80c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
81c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            INetworkPolicyListener>();
82c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
83d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    // TODO: periodically poll network stats and write to disk
84d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    // TODO: save/restore policy information from disk
85d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
86c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    // TODO: keep whitelist of system-critical services that should never have
87c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    // rules enforced, such as system, phone, and radio UIDs.
88c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
89a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    public NetworkPolicyManagerService(
90a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            Context context, IActivityManager activityManager, IPowerManager powerManager) {
91a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mContext = checkNotNull(context, "missing context");
92a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mActivityManager = checkNotNull(activityManager, "missing activityManager");
93a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mPowerManager = checkNotNull(powerManager, "missing powerManager");
94a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
95d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
96a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    public void systemReady() {
97a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // TODO: read current policy+stats from disk and generate NMS rules
98d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
99a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        updateScreenOn();
100d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
101a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        try {
102a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            mActivityManager.registerProcessObserver(mProcessObserver);
103a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        } catch (RemoteException e) {
104a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // ouch, no foregroundActivities updates means some processes may
105a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // never get network access.
106a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            Slog.e(TAG, "unable to register IProcessObserver", e);
107a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
108d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
109a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // TODO: traverse existing processes to know foreground state, or have
110a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // activitymanager dispatch current state when new observer attached.
111d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
112a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        final IntentFilter screenFilter = new IntentFilter();
113a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
114a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
115a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mContext.registerReceiver(mScreenReceiver, screenFilter);
116d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
117a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        final IntentFilter shutdownFilter = new IntentFilter();
118a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        shutdownFilter.addAction(Intent.ACTION_SHUTDOWN);
119a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
120d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
121a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
122d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
123a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
124a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
125a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
126a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // only someone like AMS should only be calling us
127a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            mContext.enforceCallingOrSelfPermission(
128a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    MANAGE_APP_TOKENS, "requires MANAGE_APP_TOKENS permission");
129a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
130a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
131a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // because a uid can have multiple pids running inside, we need to
132a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // remember all pid states and summarize foreground at uid level.
133a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
134a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // record foreground for this specific pid
135a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
136a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                if (pidForeground == null) {
137a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    pidForeground = new SparseBooleanArray(2);
138a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    mUidPidForeground.put(uid, pidForeground);
139a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                }
140a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                pidForeground.put(pid, foregroundActivities);
141a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                computeUidForegroundL(uid);
142a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
143d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
144d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
145a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
146a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onProcessDied(int pid, int uid) {
147a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // only someone like AMS should only be calling us
148a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            mContext.enforceCallingOrSelfPermission(
149a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    MANAGE_APP_TOKENS, "requires MANAGE_APP_TOKENS permission");
150a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
151a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
152a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // clear records and recompute, when they exist
153a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
154a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                if (pidForeground != null) {
155a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    pidForeground.delete(pid);
156a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                    computeUidForegroundL(uid);
157a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                }
158a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
159a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
160a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    };
161a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
162a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
163a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
164a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onReceive(Context context, Intent intent) {
165a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            synchronized (mRulesLock) {
166a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // screen-related broadcasts are protected by system, no need
167a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                // for permissions check.
168a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                updateScreenOn();
169a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
170a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
171a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    };
172d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
173a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
174a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
175a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onReceive(Context context, Intent intent) {
176a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            // TODO: persist any pending stats during clean shutdown
177a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            Log.d(TAG, "persisting stats");
178d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
179a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    };
180d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
181d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    @Override
182d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    public void setUidPolicy(int uid, int policy) {
183c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // TODO: create permission for modifying data policy
184d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        mContext.enforceCallingOrSelfPermission(
185d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey                UPDATE_DEVICE_STATS, "requires UPDATE_DEVICE_STATS permission");
186a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
187c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        final int oldPolicy;
188a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
189c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            oldPolicy = getUidPolicy(uid);
190a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            mUidPolicy.put(uid, policy);
1919599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey            updateRulesForUidL(uid);
192a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
193c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
194c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // TODO: consider dispatching BACKGROUND_DATA_SETTING broadcast
195d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
196d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
197d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    @Override
198d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    public int getUidPolicy(int uid) {
199a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
200a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            return mUidPolicy.get(uid, POLICY_NONE);
201a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
202d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
203d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
204c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    @Override
205c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    public void registerListener(INetworkPolicyListener listener) {
206c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.register(listener);
207c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
208c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        synchronized (mRulesLock) {
209c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            // dispatch any existing rules to new listeners
210c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            final int size = mUidRules.size();
211c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            for (int i = 0; i < size; i++) {
212c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                final int uid = mUidRules.keyAt(i);
213c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                final int uidRules = mUidRules.valueAt(i);
214c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                if (uidRules != RULE_ALLOW_ALL) {
215c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                    try {
216c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                        listener.onRulesChanged(uid, uidRules);
217c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                    } catch (RemoteException e) {
218c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                    }
219c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                }
220c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            }
221c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        }
222c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
223c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
224c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    @Override
225c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    public void unregisterListener(INetworkPolicyListener listener) {
226c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.unregister(listener);
227c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
228c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
2291b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    @Override
2301b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
2311b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        mContext.enforceCallingOrSelfPermission(DUMP, "requires DUMP permission");
2321b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
2331b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        synchronized (mRulesLock) {
2341b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            fout.println("Policy status for known UIDs:");
2351b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
2361b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            final SparseBooleanArray knownUids = new SparseBooleanArray();
2371b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidPolicy, knownUids);
2381b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidForeground, knownUids);
2391b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidRules, knownUids);
2401b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
2411b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            final int size = knownUids.size();
2421b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            for (int i = 0; i < size; i++) {
2431b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int uid = knownUids.keyAt(i);
2441b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print("  UID=");
2451b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(uid);
2461b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
2471b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" policy=");
2481b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int policyIndex = mUidPolicy.indexOfKey(uid);
2491b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (policyIndex < 0) {
2501b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
2511b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
2521b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpPolicy(fout, mUidPolicy.valueAt(policyIndex));
2531b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
2541b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
2551b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" foreground=");
2561b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
2571b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (foregroundIndex < 0) {
2581b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
2591b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
2601b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex));
2611b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
2621b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
2631b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" rules=");
2641b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int rulesIndex = mUidRules.indexOfKey(uid);
2651b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (rulesIndex < 0) {
2661b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
2671b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
2681b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpRules(fout, mUidRules.valueAt(rulesIndex));
2691b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
2701b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
2711b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.println();
2721b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            }
2731b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
2741b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
2759599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey
2769599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey    @Override
2779599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey    public boolean isUidForeground(int uid) {
2789599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        synchronized (mRulesLock) {
2799599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey            // only really in foreground when screen is also on
2809599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey            return mUidForeground.get(uid, false) && mScreenOn;
2819599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        }
282c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
283c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
284d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    /**
285d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey     * Foreground for PID changed; recompute foreground at UID level. If
286a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey     * changed, will trigger {@link #updateRulesForUidL(int)}.
287d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey     */
288a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private void computeUidForegroundL(int uid) {
289d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
290d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
291d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        // current pid is dropping foreground; examine other pids
292d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        boolean uidForeground = false;
293d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final int size = pidForeground.size();
294d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        for (int i = 0; i < size; i++) {
295d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            if (pidForeground.valueAt(i)) {
296d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey                uidForeground = true;
297d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey                break;
298d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            }
299d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
300d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
301d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final boolean oldUidForeground = mUidForeground.get(uid, false);
302d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        if (oldUidForeground != uidForeground) {
303d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            // foreground changed, push updated rules
304d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey            mUidForeground.put(uid, uidForeground);
305a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            updateRulesForUidL(uid);
306a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
307a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
308a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
309a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private void updateScreenOn() {
310a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
311a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            try {
312a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                mScreenOn = mPowerManager.isScreenOn();
313a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            } catch (RemoteException e) {
314a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
315a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            updateRulesForScreenL();
316d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
317d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
318d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
319a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    /**
320a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey     * Update rules that might be changed by {@link #mScreenOn} value.
321a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey     */
322a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private void updateRulesForScreenL() {
323a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // only update rules for anyone with foreground activities
324a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        final int size = mUidForeground.size();
325a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        for (int i = 0; i < size; i++) {
326a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            if (mUidForeground.valueAt(i)) {
327a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                final int uid = mUidForeground.keyAt(i);
328a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey                updateRulesForUidL(uid);
329a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
330a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
331a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
332a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
333a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private void updateRulesForUidL(int uid) {
334d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        final int uidPolicy = getUidPolicy(uid);
3359599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        final boolean uidForeground = isUidForeground(uid);
336d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
337c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // derive active rules based on policy and active state
338c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        int uidRules = RULE_ALLOW_ALL;
339c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        if (!uidForeground && (uidPolicy & POLICY_REJECT_PAID_BACKGROUND) != 0) {
340c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            // uid in background, and policy says to block paid data
341c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            uidRules = RULE_REJECT_PAID;
342d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
343d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
344c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // TODO: only dispatch when rules actually change
345c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
346c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // record rule locally to dispatch to new listeners
347c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mUidRules.put(uid, uidRules);
348c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
349c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // dispatch changed rule to existing listeners
350c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        final int length = mListeners.beginBroadcast();
351c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        for (int i = 0; i < length; i++) {
352c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
353c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            if (listener != null) {
354c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                try {
355c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                    listener.onRulesChanged(uid, uidRules);
356c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                } catch (RemoteException e) {
357c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey                }
358c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey            }
359d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
360c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.finishBroadcast();
361d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
362d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
363a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private static <T> T checkNotNull(T value, String message) {
364a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        if (value == null) {
365a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            throw new NullPointerException(message);
366a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
367a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        return value;
368a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
3691b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
3701b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
3711b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = source.size();
3721b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
3731b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            target.put(source.keyAt(i), true);
3741b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
3751b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
3761b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
3771b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) {
3781b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = source.size();
3791b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
3801b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            target.put(source.keyAt(i), true);
3811b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
3821b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
3831b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
3841b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) {
3851b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        fout.print("[");
3861b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = value.size();
3871b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
3881b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            fout.print(value.keyAt(i) + "=" + value.valueAt(i));
3891b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            if (i < size - 1) fout.print(",");
3901b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
3911b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        fout.print("]");
3921b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
393d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey}
394