NetworkPolicyManagerService.java revision 41ff7ec82422a5b6d00892afdb3232bc0e53d851
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.net;
18
19import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
20import static android.Manifest.permission.DUMP;
21import static android.Manifest.permission.MANAGE_APP_TOKENS;
22import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
23import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
24import static android.Manifest.permission.READ_PHONE_STATE;
25import static android.content.Intent.ACTION_PACKAGE_ADDED;
26import static android.content.Intent.ACTION_UID_REMOVED;
27import static android.content.Intent.EXTRA_UID;
28import static android.net.ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED;
29import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
30import static android.net.ConnectivityManager.TYPE_MOBILE;
31import static android.net.NetworkPolicy.LIMIT_DISABLED;
32import static android.net.NetworkPolicy.SNOOZE_NEVER;
33import static android.net.NetworkPolicy.WARNING_DISABLED;
34import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
35import static android.net.NetworkPolicyManager.POLICY_NONE;
36import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
37import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
38import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
39import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
40import static android.net.NetworkPolicyManager.dumpPolicy;
41import static android.net.NetworkPolicyManager.dumpRules;
42import static android.net.NetworkPolicyManager.isUidValidForPolicy;
43import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
44import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
45import static android.net.NetworkTemplate.buildTemplateMobileAll;
46import static android.text.format.DateUtils.DAY_IN_MILLIS;
47import static com.android.internal.util.Preconditions.checkNotNull;
48import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
49import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
50import static org.xmlpull.v1.XmlPullParser.START_TAG;
51
52import android.app.IActivityManager;
53import android.app.INotificationManager;
54import android.app.IProcessObserver;
55import android.app.Notification;
56import android.app.PendingIntent;
57import android.content.BroadcastReceiver;
58import android.content.ComponentName;
59import android.content.Context;
60import android.content.Intent;
61import android.content.IntentFilter;
62import android.content.pm.ApplicationInfo;
63import android.content.pm.PackageManager;
64import android.content.res.Resources;
65import android.net.ConnectivityManager;
66import android.net.IConnectivityManager;
67import android.net.INetworkManagementEventObserver;
68import android.net.INetworkPolicyListener;
69import android.net.INetworkPolicyManager;
70import android.net.INetworkStatsService;
71import android.net.NetworkIdentity;
72import android.net.NetworkPolicy;
73import android.net.NetworkState;
74import android.net.NetworkStats;
75import android.net.NetworkTemplate;
76import android.os.Environment;
77import android.os.Handler;
78import android.os.HandlerThread;
79import android.os.INetworkManagementService;
80import android.os.IPowerManager;
81import android.os.Message;
82import android.os.RemoteCallbackList;
83import android.os.RemoteException;
84import android.telephony.TelephonyManager;
85import android.text.format.Formatter;
86import android.text.format.Time;
87import android.util.NtpTrustedTime;
88import android.util.Slog;
89import android.util.SparseArray;
90import android.util.SparseBooleanArray;
91import android.util.SparseIntArray;
92import android.util.TrustedTime;
93import android.util.Xml;
94
95import com.android.internal.R;
96import com.android.internal.os.AtomicFile;
97import com.android.internal.util.FastXmlSerializer;
98import com.google.android.collect.Lists;
99import com.google.android.collect.Maps;
100import com.google.android.collect.Sets;
101
102import org.xmlpull.v1.XmlPullParser;
103import org.xmlpull.v1.XmlPullParserException;
104import org.xmlpull.v1.XmlSerializer;
105
106import java.io.File;
107import java.io.FileDescriptor;
108import java.io.FileInputStream;
109import java.io.FileNotFoundException;
110import java.io.FileOutputStream;
111import java.io.IOException;
112import java.io.PrintWriter;
113import java.net.ProtocolException;
114import java.util.ArrayList;
115import java.util.Arrays;
116import java.util.HashMap;
117import java.util.HashSet;
118import java.util.List;
119
120import libcore.io.IoUtils;
121
122/**
123 * Service that maintains low-level network policy rules and collects usage
124 * statistics to drive those rules.
125 * <p>
126 * Derives active rules by combining a given policy with other system status,
127 * and delivers to listeners, such as {@link ConnectivityManager}, for
128 * enforcement.
129 */
130public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
131    private static final String TAG = "NetworkPolicy";
132    private static final boolean LOGD = true;
133    private static final boolean LOGV = false;
134
135    private static final int VERSION_INIT = 1;
136    private static final int VERSION_ADDED_SNOOZE = 2;
137
138    private static final long KB_IN_BYTES = 1024;
139    private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
140    private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
141
142    // @VisibleForTesting
143    public static final int TYPE_WARNING = 0x1;
144    public static final int TYPE_LIMIT = 0x2;
145    public static final int TYPE_LIMIT_SNOOZED = 0x3;
146
147    private static final String TAG_POLICY_LIST = "policy-list";
148    private static final String TAG_NETWORK_POLICY = "network-policy";
149    private static final String TAG_UID_POLICY = "uid-policy";
150
151    private static final String ATTR_VERSION = "version";
152    private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
153    private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
154    private static final String ATTR_CYCLE_DAY = "cycleDay";
155    private static final String ATTR_WARNING_BYTES = "warningBytes";
156    private static final String ATTR_LIMIT_BYTES = "limitBytes";
157    private static final String ATTR_LAST_SNOOZE = "lastSnooze";
158    private static final String ATTR_UID = "uid";
159    private static final String ATTR_POLICY = "policy";
160
161    private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
162
163    private static final int MSG_RULES_CHANGED = 0x1;
164    private static final int MSG_METERED_IFACES_CHANGED = 0x2;
165
166    private final Context mContext;
167    private final IActivityManager mActivityManager;
168    private final IPowerManager mPowerManager;
169    private final INetworkStatsService mNetworkStats;
170    private final INetworkManagementService mNetworkManager;
171    private final TrustedTime mTime;
172
173    private IConnectivityManager mConnManager;
174    private INotificationManager mNotifManager;
175
176    private final Object mRulesLock = new Object();
177
178    private boolean mScreenOn;
179    private boolean mBackgroundData;
180
181    /** Defined network policies. */
182    private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap();
183    /** Currently active network rules for ifaces. */
184    private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap();
185
186    /** Defined UID policies. */
187    private SparseIntArray mUidPolicy = new SparseIntArray();
188    /** Currently derived rules for each UID. */
189    private SparseIntArray mUidRules = new SparseIntArray();
190
191    /** Set of ifaces that are metered. */
192    private HashSet<String> mMeteredIfaces = Sets.newHashSet();
193    /** Set of over-limit templates that have been notified. */
194    private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet();
195
196    /** Foreground at both UID and PID granularity. */
197    private SparseBooleanArray mUidForeground = new SparseBooleanArray();
198    private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
199            SparseBooleanArray>();
200
201    private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
202            INetworkPolicyListener>();
203
204    private final HandlerThread mHandlerThread;
205    private final Handler mHandler;
206
207    private final AtomicFile mPolicyFile;
208
209    // TODO: keep whitelist of system-critical services that should never have
210    // rules enforced, such as system, phone, and radio UIDs.
211
212    // TODO: migrate notifications to SystemUI
213
214    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
215            IPowerManager powerManager, INetworkStatsService networkStats,
216            INetworkManagementService networkManagement) {
217        this(context, activityManager, powerManager, networkStats, networkManagement,
218                NtpTrustedTime.getInstance(context), getSystemDir());
219    }
220
221    private static File getSystemDir() {
222        return new File(Environment.getDataDirectory(), "system");
223    }
224
225    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
226            IPowerManager powerManager, INetworkStatsService networkStats,
227            INetworkManagementService networkManagement,
228            TrustedTime time, File systemDir) {
229        mContext = checkNotNull(context, "missing context");
230        mActivityManager = checkNotNull(activityManager, "missing activityManager");
231        mPowerManager = checkNotNull(powerManager, "missing powerManager");
232        mNetworkStats = checkNotNull(networkStats, "missing networkStats");
233        mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
234        mTime = checkNotNull(time, "missing TrustedTime");
235
236        mHandlerThread = new HandlerThread(TAG);
237        mHandlerThread.start();
238        mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
239
240        mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
241    }
242
243    public void bindConnectivityManager(IConnectivityManager connManager) {
244        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
245    }
246
247    public void bindNotificationManager(INotificationManager notifManager) {
248        mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
249    }
250
251    public void systemReady() {
252        synchronized (mRulesLock) {
253            // read policy from disk
254            readPolicyLocked();
255        }
256
257        updateScreenOn();
258        updateBackgroundData(true);
259
260        try {
261            mActivityManager.registerProcessObserver(mProcessObserver);
262        } catch (RemoteException e) {
263            // ouch, no foregroundActivities updates means some processes may
264            // never get network access.
265            Slog.e(TAG, "unable to register IProcessObserver", e);
266        }
267
268        try {
269            mNetworkManager.registerObserver(mAlertObserver);
270        } catch (RemoteException e) {
271            // ouch, no alert updates means we fall back to
272            // ACTION_NETWORK_STATS_UPDATED broadcasts.
273            Slog.e(TAG, "unable to register INetworkManagementEventObserver", e);
274        }
275
276        // TODO: traverse existing processes to know foreground state, or have
277        // activitymanager dispatch current state when new observer attached.
278
279        final IntentFilter screenFilter = new IntentFilter();
280        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
281        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
282        mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler);
283
284        // watch for network interfaces to be claimed
285        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
286        mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
287
288        // listen for package/uid changes to update policy
289        final IntentFilter packageFilter = new IntentFilter();
290        packageFilter.addAction(ACTION_PACKAGE_ADDED);
291        packageFilter.addAction(ACTION_UID_REMOVED);
292        mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
293
294        // listen for stats update events
295        final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
296        mContext.registerReceiver(
297                mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
298
299        // listen for changes to background data flag
300        final IntentFilter bgFilter = new IntentFilter(ACTION_BACKGROUND_DATA_SETTING_CHANGED);
301        mContext.registerReceiver(mBgReceiver, bgFilter, CONNECTIVITY_INTERNAL, mHandler);
302
303    }
304
305    private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
306        @Override
307        public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
308            // only someone like AMS should only be calling us
309            mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
310
311            synchronized (mRulesLock) {
312                // because a uid can have multiple pids running inside, we need to
313                // remember all pid states and summarize foreground at uid level.
314
315                // record foreground for this specific pid
316                SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
317                if (pidForeground == null) {
318                    pidForeground = new SparseBooleanArray(2);
319                    mUidPidForeground.put(uid, pidForeground);
320                }
321                pidForeground.put(pid, foregroundActivities);
322                computeUidForegroundLocked(uid);
323            }
324        }
325
326        @Override
327        public void onProcessDied(int pid, int uid) {
328            // only someone like AMS should only be calling us
329            mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
330
331            synchronized (mRulesLock) {
332                // clear records and recompute, when they exist
333                final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
334                if (pidForeground != null) {
335                    pidForeground.delete(pid);
336                    computeUidForegroundLocked(uid);
337                }
338            }
339        }
340    };
341
342    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
343        @Override
344        public void onReceive(Context context, Intent intent) {
345            synchronized (mRulesLock) {
346                // screen-related broadcasts are protected by system, no need
347                // for permissions check.
348                updateScreenOn();
349            }
350        }
351    };
352
353    private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
354        @Override
355        public void onReceive(Context context, Intent intent) {
356            // on background handler thread, and PACKAGE_ADDED and UID_REMOVED
357            // are protected broadcasts.
358
359            final String action = intent.getAction();
360            final int uid = intent.getIntExtra(EXTRA_UID, 0);
361            synchronized (mRulesLock) {
362                if (ACTION_PACKAGE_ADDED.equals(action)) {
363                    // update rules for UID, since it might be subject to
364                    // global background data policy.
365                    if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
366                    updateRulesForUidLocked(uid);
367
368                } else if (ACTION_UID_REMOVED.equals(action)) {
369                    // remove any policy and update rules to clean up.
370                    if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
371                    mUidPolicy.delete(uid);
372                    updateRulesForUidLocked(uid);
373                    writePolicyLocked();
374                }
375            }
376        }
377    };
378
379    /**
380     * Receiver that watches for {@link INetworkStatsService} updates, which we
381     * use to check against {@link NetworkPolicy#warningBytes}.
382     */
383    private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
384        @Override
385        public void onReceive(Context context, Intent intent) {
386            // on background handler thread, and verified
387            // READ_NETWORK_USAGE_HISTORY permission above.
388
389            synchronized (mRulesLock) {
390                updateNotificationsLocked();
391            }
392        }
393    };
394
395    /**
396     * Receiver that watches for
397     * {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}.
398     */
399    private BroadcastReceiver mBgReceiver = new BroadcastReceiver() {
400        @Override
401        public void onReceive(Context context, Intent intent) {
402            // on background handler thread, and verified CONNECTIVITY_INTERNAL
403            // permission above.
404
405            synchronized (mRulesLock) {
406                updateBackgroundData(false);
407            }
408        }
409    };
410
411    /**
412     * Observer that watches for {@link INetworkManagementService} alerts.
413     */
414    private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
415        @Override
416        public void limitReached(String limitName, String iface) {
417            // only someone like NMS should be calling us
418            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
419
420            synchronized (mRulesLock) {
421                if (mMeteredIfaces.contains(iface)) {
422                    try {
423                        // force stats update to make sure we have numbers that
424                        // caused alert to trigger.
425                        mNetworkStats.forceUpdate();
426                    } catch (RemoteException e) {
427                        Slog.w(TAG, "problem updating network stats");
428                    }
429
430                    updateNotificationsLocked();
431                }
432            }
433        }
434    };
435
436    /**
437     * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
438     * to show visible notifications as needed.
439     */
440    private void updateNotificationsLocked() {
441        if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
442
443        // try refreshing time source when stale
444        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
445            mTime.forceRefresh();
446        }
447
448        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
449                : System.currentTimeMillis();
450
451        // TODO: when switching to kernel notifications, compute next future
452        // cycle boundary to recompute notifications.
453
454        // examine stats for each active policy
455        for (NetworkPolicy policy : mNetworkRules.keySet()) {
456            final long start = computeLastCycleBoundary(currentTime, policy);
457            final long end = currentTime;
458
459            final long totalBytes;
460            try {
461                final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
462                        policy.template, start, end);
463                final NetworkStats.Entry entry = stats.getValues(0, null);
464                totalBytes = entry.rxBytes + entry.txBytes;
465            } catch (RemoteException e) {
466                Slog.w(TAG, "problem reading summary for template " + policy.template);
467                continue;
468            }
469
470            if (policy.limitBytes != LIMIT_DISABLED && totalBytes >= policy.limitBytes) {
471                cancelNotification(policy, TYPE_WARNING);
472
473                if (policy.lastSnooze >= start) {
474                    cancelNotification(policy, TYPE_LIMIT);
475                    enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
476                } else {
477                    cancelNotification(policy, TYPE_LIMIT_SNOOZED);
478                    enqueueNotification(policy, TYPE_LIMIT, totalBytes);
479                    notifyOverLimitLocked(policy.template);
480                }
481
482            } else {
483                cancelNotification(policy, TYPE_LIMIT);
484                cancelNotification(policy, TYPE_LIMIT_SNOOZED);
485                notifyUnderLimitLocked(policy.template);
486
487                if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) {
488                    enqueueNotification(policy, TYPE_WARNING, totalBytes);
489                } else {
490                    cancelNotification(policy, TYPE_WARNING);
491                }
492            }
493        }
494
495        // clear notifications for non-active policies
496        for (NetworkPolicy policy : mNetworkPolicy.values()) {
497            if (!mNetworkRules.containsKey(policy)) {
498                cancelNotification(policy, TYPE_WARNING);
499                cancelNotification(policy, TYPE_LIMIT);
500                cancelNotification(policy, TYPE_LIMIT_SNOOZED);
501                notifyUnderLimitLocked(policy.template);
502            }
503        }
504    }
505
506    /**
507     * Notify that given {@link NetworkTemplate} is over
508     * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
509     */
510    private void notifyOverLimitLocked(NetworkTemplate template) {
511        if (!mOverLimitNotified.contains(template)) {
512            mContext.startActivity(buildNetworkOverLimitIntent(template));
513            mOverLimitNotified.add(template);
514        }
515    }
516
517    private void notifyUnderLimitLocked(NetworkTemplate template) {
518        mOverLimitNotified.remove(template);
519    }
520
521    /**
522     * Build unique tag that identifies an active {@link NetworkPolicy}
523     * notification of a specific type, like {@link #TYPE_LIMIT}.
524     */
525    private String buildNotificationTag(NetworkPolicy policy, int type) {
526        return TAG + ":" + policy.template.hashCode() + ":" + type;
527    }
528
529    /**
530     * Show notification for combined {@link NetworkPolicy} and specific type,
531     * like {@link #TYPE_LIMIT}. Okay to call multiple times.
532     */
533    private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
534        final String tag = buildNotificationTag(policy, type);
535        final Notification.Builder builder = new Notification.Builder(mContext);
536        builder.setOnlyAlertOnce(true);
537        builder.setOngoing(true);
538
539        final Resources res = mContext.getResources();
540        switch (type) {
541            case TYPE_WARNING: {
542                final CharSequence title = res.getText(R.string.data_usage_warning_title);
543                final CharSequence body = res.getString(R.string.data_usage_warning_body,
544                        Formatter.formatFileSize(mContext, policy.warningBytes));
545
546                builder.setSmallIcon(R.drawable.ic_menu_info_details);
547                builder.setTicker(title);
548                builder.setContentTitle(title);
549                builder.setContentText(body);
550
551                final Intent intent = buildViewDataUsageIntent(policy.template);
552                builder.setContentIntent(PendingIntent.getActivity(
553                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
554                break;
555            }
556            case TYPE_LIMIT: {
557                final CharSequence body = res.getText(R.string.data_usage_limit_body);
558
559                final CharSequence title;
560                switch (policy.template.getMatchRule()) {
561                    case MATCH_MOBILE_3G_LOWER:
562                        title = res.getText(R.string.data_usage_3g_limit_title);
563                        break;
564                    case MATCH_MOBILE_4G:
565                        title = res.getText(R.string.data_usage_4g_limit_title);
566                        break;
567                    default:
568                        title = res.getText(R.string.data_usage_mobile_limit_title);
569                        break;
570                }
571
572                builder.setSmallIcon(com.android.internal.R.drawable.ic_menu_block);
573                builder.setTicker(title);
574                builder.setContentTitle(title);
575                builder.setContentText(body);
576
577                final Intent intent = buildNetworkOverLimitIntent(policy.template);
578                builder.setContentIntent(PendingIntent.getActivity(
579                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
580                break;
581            }
582            case TYPE_LIMIT_SNOOZED: {
583                final long overBytes = totalBytes - policy.limitBytes;
584                final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body,
585                        Formatter.formatFileSize(mContext, overBytes));
586
587                final CharSequence title;
588                switch (policy.template.getMatchRule()) {
589                    case MATCH_MOBILE_3G_LOWER:
590                        title = res.getText(R.string.data_usage_3g_limit_snoozed_title);
591                        break;
592                    case MATCH_MOBILE_4G:
593                        title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
594                        break;
595                    default:
596                        title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
597                        break;
598                }
599
600                builder.setSmallIcon(R.drawable.ic_menu_info_details);
601                builder.setTicker(title);
602                builder.setContentTitle(title);
603                builder.setContentText(body);
604
605                final Intent intent = buildViewDataUsageIntent(policy.template);
606                builder.setContentIntent(PendingIntent.getActivity(
607                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
608                break;
609            }
610        }
611
612        // TODO: move to NotificationManager once we can mock it
613        try {
614            final String packageName = mContext.getPackageName();
615            final int[] idReceived = new int[1];
616            mNotifManager.enqueueNotificationWithTag(
617                    packageName, tag, 0x0, builder.getNotification(), idReceived);
618        } catch (RemoteException e) {
619            Slog.w(TAG, "problem during enqueueNotification: " + e);
620        }
621    }
622
623    /**
624     * Cancel any notification for combined {@link NetworkPolicy} and specific
625     * type, like {@link #TYPE_LIMIT}.
626     */
627    private void cancelNotification(NetworkPolicy policy, int type) {
628        final String tag = buildNotificationTag(policy, type);
629
630        // TODO: move to NotificationManager once we can mock it
631        try {
632            final String packageName = mContext.getPackageName();
633            mNotifManager.cancelNotificationWithTag(packageName, tag, 0x0);
634        } catch (RemoteException e) {
635            Slog.w(TAG, "problem during enqueueNotification: " + e);
636        }
637    }
638
639    /**
640     * Receiver that watches for {@link IConnectivityManager} to claim network
641     * interfaces. Used to apply {@link NetworkPolicy} to matching networks.
642     */
643    private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
644        @Override
645        public void onReceive(Context context, Intent intent) {
646            // on background handler thread, and verified CONNECTIVITY_INTERNAL
647            // permission above.
648            synchronized (mRulesLock) {
649                ensureActiveMobilePolicyLocked();
650                updateNetworkRulesLocked();
651                updateNotificationsLocked();
652            }
653        }
654    };
655
656    /**
657     * Examine all connected {@link NetworkState}, looking for
658     * {@link NetworkPolicy} that need to be enforced. When matches found, set
659     * remaining quota based on usage cycle and historical stats.
660     */
661    private void updateNetworkRulesLocked() {
662        if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
663
664        final NetworkState[] states;
665        try {
666            states = mConnManager.getAllNetworkState();
667        } catch (RemoteException e) {
668            Slog.w(TAG, "problem reading network state");
669            return;
670        }
671
672        // first, derive identity for all connected networks, which can be used
673        // to match against templates.
674        final HashMap<NetworkIdentity, String> networks = Maps.newHashMap();
675        for (NetworkState state : states) {
676            // stash identity and iface away for later use
677            if (state.networkInfo.isConnected()) {
678                final String iface = state.linkProperties.getInterfaceName();
679                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
680                networks.put(ident, iface);
681            }
682        }
683
684        // build list of rules and ifaces to enforce them against
685        mNetworkRules.clear();
686        final ArrayList<String> ifaceList = Lists.newArrayList();
687        for (NetworkPolicy policy : mNetworkPolicy.values()) {
688
689            // collect all active ifaces that match this template
690            ifaceList.clear();
691            for (NetworkIdentity ident : networks.keySet()) {
692                if (policy.template.matches(ident)) {
693                    final String iface = networks.get(ident);
694                    ifaceList.add(iface);
695                }
696            }
697
698            if (ifaceList.size() > 0) {
699                final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
700                mNetworkRules.put(policy, ifaces);
701            }
702        }
703
704        // try refreshing time source when stale
705        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
706            mTime.forceRefresh();
707        }
708
709        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
710                : System.currentTimeMillis();
711
712        final HashSet<String> newMeteredIfaces = Sets.newHashSet();
713
714        // apply each policy that we found ifaces for; compute remaining data
715        // based on current cycle and historical stats, and push to kernel.
716        for (NetworkPolicy policy : mNetworkRules.keySet()) {
717            final String[] ifaces = mNetworkRules.get(policy);
718
719            final long start = computeLastCycleBoundary(currentTime, policy);
720            final long end = currentTime;
721
722            final NetworkStats stats;
723            final long total;
724            try {
725                stats = mNetworkStats.getSummaryForNetwork(policy.template, start, end);
726                final NetworkStats.Entry entry = stats.getValues(0, null);
727                total = entry.rxBytes + entry.txBytes;
728            } catch (RemoteException e) {
729                Slog.w(TAG, "problem reading summary for template " + policy.template);
730                continue;
731            }
732
733            if (LOGD) {
734                Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
735                        + Arrays.toString(ifaces));
736            }
737
738            final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
739            final boolean hasWarning = policy.warningBytes != WARNING_DISABLED;
740
741            if (hasLimit || hasWarning) {
742                final long quotaBytes;
743                if (hasLimit) {
744                    // remaining "quota" is based on usage in current cycle
745                    quotaBytes = Math.max(0, policy.limitBytes - total);
746                } else {
747                    // to track warning alert later, use a high quota
748                    quotaBytes = Long.MAX_VALUE;
749                }
750
751                if (ifaces.length > 1) {
752                    // TODO: switch to shared quota once NMS supports
753                    Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
754                }
755
756                for (String iface : ifaces) {
757                    removeInterfaceQuota(iface);
758                    if (quotaBytes > 0) {
759                        setInterfaceQuota(iface, quotaBytes);
760                        newMeteredIfaces.add(iface);
761                    }
762                }
763            }
764
765            if (hasWarning) {
766                final long alertBytes = Math.max(0, policy.warningBytes - total);
767                for (String iface : ifaces) {
768                    removeInterfaceAlert(iface);
769                    if (alertBytes > 0) {
770                        setInterfaceAlert(iface, alertBytes);
771                    }
772                }
773            }
774        }
775
776        // remove quota on any trailing interfaces
777        for (String iface : mMeteredIfaces) {
778            if (!newMeteredIfaces.contains(iface)) {
779                removeInterfaceQuota(iface);
780            }
781        }
782        mMeteredIfaces = newMeteredIfaces;
783
784        final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
785        mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
786    }
787
788    /**
789     * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
790     * have at least a default mobile policy defined.
791     */
792    private void ensureActiveMobilePolicyLocked() {
793        if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
794        final String subscriberId = getActiveSubscriberId();
795        final NetworkIdentity probeIdent = new NetworkIdentity(
796                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false);
797
798        // examine to see if any policy is defined for active mobile
799        boolean mobileDefined = false;
800        for (NetworkPolicy policy : mNetworkPolicy.values()) {
801            if (policy.template.matches(probeIdent)) {
802                mobileDefined = true;
803            }
804        }
805
806        if (!mobileDefined) {
807            Slog.i(TAG, "no policy for active mobile network; generating default policy");
808
809            // build default mobile policy, and assume usage cycle starts today
810            final long warningBytes = mContext.getResources().getInteger(
811                    com.android.internal.R.integer.config_networkPolicyDefaultWarning)
812                    * MB_IN_BYTES;
813
814            final Time time = new Time(Time.TIMEZONE_UTC);
815            time.setToNow();
816            final int cycleDay = time.monthDay;
817
818            final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
819            mNetworkPolicy.put(template, new NetworkPolicy(
820                    template, cycleDay, warningBytes, LIMIT_DISABLED, SNOOZE_NEVER));
821            writePolicyLocked();
822        }
823    }
824
825    private void readPolicyLocked() {
826        if (LOGV) Slog.v(TAG, "readPolicyLocked()");
827
828        // clear any existing policy and read from disk
829        mNetworkPolicy.clear();
830        mUidPolicy.clear();
831
832        FileInputStream fis = null;
833        try {
834            fis = mPolicyFile.openRead();
835            final XmlPullParser in = Xml.newPullParser();
836            in.setInput(fis, null);
837
838            int type;
839            int version = VERSION_INIT;
840            while ((type = in.next()) != END_DOCUMENT) {
841                final String tag = in.getName();
842                if (type == START_TAG) {
843                    if (TAG_POLICY_LIST.equals(tag)) {
844                        version = readIntAttribute(in, ATTR_VERSION);
845
846                    } else if (TAG_NETWORK_POLICY.equals(tag)) {
847                        final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
848                        final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
849                        final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
850                        final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
851                        final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
852                        final long lastSnooze;
853                        if (version >= VERSION_ADDED_SNOOZE) {
854                            lastSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
855                        } else {
856                            lastSnooze = SNOOZE_NEVER;
857                        }
858
859                        final NetworkTemplate template = new NetworkTemplate(
860                                networkTemplate, subscriberId);
861                        mNetworkPolicy.put(template, new NetworkPolicy(
862                                template, cycleDay, warningBytes, limitBytes, lastSnooze));
863
864                    } else if (TAG_UID_POLICY.equals(tag)) {
865                        final int uid = readIntAttribute(in, ATTR_UID);
866                        final int policy = readIntAttribute(in, ATTR_POLICY);
867
868                        if (isUidValidForPolicy(mContext, uid)) {
869                            setUidPolicyUnchecked(uid, policy, false);
870                        } else {
871                            Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
872                        }
873                    }
874                }
875            }
876
877        } catch (FileNotFoundException e) {
878            // missing policy is okay, probably first boot
879        } catch (IOException e) {
880            Slog.e(TAG, "problem reading network stats", e);
881        } catch (XmlPullParserException e) {
882            Slog.e(TAG, "problem reading network stats", e);
883        } finally {
884            IoUtils.closeQuietly(fis);
885        }
886    }
887
888    private void writePolicyLocked() {
889        if (LOGV) Slog.v(TAG, "writePolicyLocked()");
890
891        FileOutputStream fos = null;
892        try {
893            fos = mPolicyFile.startWrite();
894
895            XmlSerializer out = new FastXmlSerializer();
896            out.setOutput(fos, "utf-8");
897            out.startDocument(null, true);
898
899            out.startTag(null, TAG_POLICY_LIST);
900            writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_SNOOZE);
901
902            // write all known network policies
903            for (NetworkPolicy policy : mNetworkPolicy.values()) {
904                final NetworkTemplate template = policy.template;
905
906                out.startTag(null, TAG_NETWORK_POLICY);
907                writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
908                final String subscriberId = template.getSubscriberId();
909                if (subscriberId != null) {
910                    out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
911                }
912                writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
913                writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
914                writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
915                writeLongAttribute(out, ATTR_LAST_SNOOZE, policy.lastSnooze);
916                out.endTag(null, TAG_NETWORK_POLICY);
917            }
918
919            // write all known uid policies
920            for (int i = 0; i < mUidPolicy.size(); i++) {
921                final int uid = mUidPolicy.keyAt(i);
922                final int policy = mUidPolicy.valueAt(i);
923
924                // skip writing empty policies
925                if (policy == POLICY_NONE) continue;
926
927                out.startTag(null, TAG_UID_POLICY);
928                writeIntAttribute(out, ATTR_UID, uid);
929                writeIntAttribute(out, ATTR_POLICY, policy);
930                out.endTag(null, TAG_UID_POLICY);
931            }
932
933            out.endTag(null, TAG_POLICY_LIST);
934            out.endDocument();
935
936            mPolicyFile.finishWrite(fos);
937        } catch (IOException e) {
938            if (fos != null) {
939                mPolicyFile.failWrite(fos);
940            }
941        }
942    }
943
944    @Override
945    public void setUidPolicy(int uid, int policy) {
946        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
947
948        if (!isUidValidForPolicy(mContext, uid)) {
949            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
950        }
951
952        setUidPolicyUnchecked(uid, policy, true);
953    }
954
955    private void setUidPolicyUnchecked(int uid, int policy, boolean persist) {
956        final int oldPolicy;
957        synchronized (mRulesLock) {
958            oldPolicy = getUidPolicy(uid);
959            mUidPolicy.put(uid, policy);
960
961            // uid policy changed, recompute rules and persist policy.
962            updateRulesForUidLocked(uid);
963            if (persist) {
964                writePolicyLocked();
965            }
966        }
967    }
968
969    @Override
970    public int getUidPolicy(int uid) {
971        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
972
973        synchronized (mRulesLock) {
974            return mUidPolicy.get(uid, POLICY_NONE);
975        }
976    }
977
978    @Override
979    public void registerListener(INetworkPolicyListener listener) {
980        // TODO: create permission for observing network policy
981        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
982
983        mListeners.register(listener);
984
985        // TODO: consider dispatching existing rules to new listeners
986    }
987
988    @Override
989    public void unregisterListener(INetworkPolicyListener listener) {
990        // TODO: create permission for observing network policy
991        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
992
993        mListeners.unregister(listener);
994    }
995
996    @Override
997    public void setNetworkPolicies(NetworkPolicy[] policies) {
998        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
999
1000        synchronized (mRulesLock) {
1001            mNetworkPolicy.clear();
1002            for (NetworkPolicy policy : policies) {
1003                mNetworkPolicy.put(policy.template, policy);
1004            }
1005
1006            updateNetworkRulesLocked();
1007            updateNotificationsLocked();
1008            writePolicyLocked();
1009        }
1010    }
1011
1012    @Override
1013    public NetworkPolicy[] getNetworkPolicies() {
1014        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1015        mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
1016
1017        synchronized (mRulesLock) {
1018            return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]);
1019        }
1020    }
1021
1022    @Override
1023    public void snoozePolicy(NetworkTemplate template) {
1024        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1025
1026        // try refreshing time source when stale
1027        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
1028            mTime.forceRefresh();
1029        }
1030
1031        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
1032                : System.currentTimeMillis();
1033
1034        synchronized (mRulesLock) {
1035            // find and snooze local policy that matches
1036            final NetworkPolicy policy = mNetworkPolicy.get(template);
1037            if (policy == null) {
1038                throw new IllegalArgumentException("unable to find policy for " + template);
1039            }
1040
1041            policy.lastSnooze = currentTime;
1042
1043            updateNetworkRulesLocked();
1044            updateNotificationsLocked();
1045            writePolicyLocked();
1046        }
1047    }
1048
1049    @Override
1050    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
1051        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
1052
1053        final HashSet<String> argSet = new HashSet<String>();
1054        for (String arg : args) {
1055            argSet.add(arg);
1056        }
1057
1058        synchronized (mRulesLock) {
1059            if (argSet.contains("unsnooze")) {
1060                for (NetworkPolicy policy : mNetworkPolicy.values()) {
1061                    policy.lastSnooze = SNOOZE_NEVER;
1062                }
1063                writePolicyLocked();
1064                fout.println("Wiped snooze timestamps");
1065                return;
1066            }
1067
1068            fout.println("Network policies:");
1069            for (NetworkPolicy policy : mNetworkPolicy.values()) {
1070                fout.print("  "); fout.println(policy.toString());
1071            }
1072
1073            fout.println("Policy status for known UIDs:");
1074
1075            final SparseBooleanArray knownUids = new SparseBooleanArray();
1076            collectKeys(mUidPolicy, knownUids);
1077            collectKeys(mUidForeground, knownUids);
1078            collectKeys(mUidRules, knownUids);
1079
1080            final int size = knownUids.size();
1081            for (int i = 0; i < size; i++) {
1082                final int uid = knownUids.keyAt(i);
1083                fout.print("  UID=");
1084                fout.print(uid);
1085
1086                fout.print(" policy=");
1087                final int policyIndex = mUidPolicy.indexOfKey(uid);
1088                if (policyIndex < 0) {
1089                    fout.print("UNKNOWN");
1090                } else {
1091                    dumpPolicy(fout, mUidPolicy.valueAt(policyIndex));
1092                }
1093
1094                fout.print(" foreground=");
1095                final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
1096                if (foregroundIndex < 0) {
1097                    fout.print("UNKNOWN");
1098                } else {
1099                    dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex));
1100                }
1101
1102                fout.print(" rules=");
1103                final int rulesIndex = mUidRules.indexOfKey(uid);
1104                if (rulesIndex < 0) {
1105                    fout.print("UNKNOWN");
1106                } else {
1107                    dumpRules(fout, mUidRules.valueAt(rulesIndex));
1108                }
1109
1110                fout.println();
1111            }
1112        }
1113    }
1114
1115    @Override
1116    public boolean isUidForeground(int uid) {
1117        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1118
1119        synchronized (mRulesLock) {
1120            // only really in foreground when screen is also on
1121            return mUidForeground.get(uid, false) && mScreenOn;
1122        }
1123    }
1124
1125    /**
1126     * Foreground for PID changed; recompute foreground at UID level. If
1127     * changed, will trigger {@link #updateRulesForUidLocked(int)}.
1128     */
1129    private void computeUidForegroundLocked(int uid) {
1130        final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
1131
1132        // current pid is dropping foreground; examine other pids
1133        boolean uidForeground = false;
1134        final int size = pidForeground.size();
1135        for (int i = 0; i < size; i++) {
1136            if (pidForeground.valueAt(i)) {
1137                uidForeground = true;
1138                break;
1139            }
1140        }
1141
1142        final boolean oldUidForeground = mUidForeground.get(uid, false);
1143        if (oldUidForeground != uidForeground) {
1144            // foreground changed, push updated rules
1145            mUidForeground.put(uid, uidForeground);
1146            updateRulesForUidLocked(uid);
1147        }
1148    }
1149
1150    private void updateScreenOn() {
1151        synchronized (mRulesLock) {
1152            try {
1153                mScreenOn = mPowerManager.isScreenOn();
1154            } catch (RemoteException e) {
1155            }
1156            updateRulesForScreenLocked();
1157        }
1158    }
1159
1160    private void updateBackgroundData(boolean systemReady) {
1161        synchronized (mRulesLock) {
1162            try {
1163                mBackgroundData = mConnManager.getBackgroundDataSetting();
1164            } catch (RemoteException e) {
1165            }
1166            if (systemReady && mBackgroundData) {
1167                // typical behavior of background enabled during systemReady;
1168                // no need to clear rules for all UIDs.
1169            } else {
1170                updateRulesForBackgroundDataLocked();
1171            }
1172        }
1173    }
1174
1175    /**
1176     * Update rules that might be changed by {@link #mScreenOn} value.
1177     */
1178    private void updateRulesForScreenLocked() {
1179        // only update rules for anyone with foreground activities
1180        final int size = mUidForeground.size();
1181        for (int i = 0; i < size; i++) {
1182            if (mUidForeground.valueAt(i)) {
1183                final int uid = mUidForeground.keyAt(i);
1184                updateRulesForUidLocked(uid);
1185            }
1186        }
1187    }
1188
1189    /**
1190     * Update rules that might be changed by {@link #mBackgroundData} value.
1191     */
1192    private void updateRulesForBackgroundDataLocked() {
1193        // update rules for all installed applications
1194        final PackageManager pm = mContext.getPackageManager();
1195        final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
1196        for (ApplicationInfo app : apps) {
1197            updateRulesForUidLocked(app.uid);
1198        }
1199
1200        // and catch system UIDs
1201        // TODO: keep in sync with android_filesystem_config.h
1202        for (int uid = 1000; uid <= 1025; uid++) {
1203            updateRulesForUidLocked(uid);
1204        }
1205        for (int uid = 2000; uid <= 2002; uid++) {
1206            updateRulesForUidLocked(uid);
1207        }
1208        for (int uid = 3000; uid <= 3007; uid++) {
1209            updateRulesForUidLocked(uid);
1210        }
1211        for (int uid = 9998; uid <= 9999; uid++) {
1212            updateRulesForUidLocked(uid);
1213        }
1214    }
1215
1216    private void updateRulesForUidLocked(int uid) {
1217        final int uidPolicy = getUidPolicy(uid);
1218        final boolean uidForeground = isUidForeground(uid);
1219
1220        // derive active rules based on policy and active state
1221        int uidRules = RULE_ALLOW_ALL;
1222        if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
1223            // uid in background, and policy says to block metered data
1224            uidRules = RULE_REJECT_METERED;
1225        }
1226        if (!uidForeground && !mBackgroundData) {
1227            // uid in background, and global background disabled
1228            uidRules = RULE_REJECT_METERED;
1229        }
1230
1231        // TODO: only dispatch when rules actually change
1232
1233        if (uidRules == RULE_ALLOW_ALL) {
1234            mUidRules.delete(uid);
1235        } else {
1236            mUidRules.put(uid, uidRules);
1237        }
1238
1239        final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
1240        setUidNetworkRules(uid, rejectMetered);
1241
1242        // dispatch changed rule to existing listeners
1243        mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
1244    }
1245
1246    private Handler.Callback mHandlerCallback = new Handler.Callback() {
1247        /** {@inheritDoc} */
1248        public boolean handleMessage(Message msg) {
1249            switch (msg.what) {
1250                case MSG_RULES_CHANGED: {
1251                    final int uid = msg.arg1;
1252                    final int uidRules = msg.arg2;
1253                    final int length = mListeners.beginBroadcast();
1254                    for (int i = 0; i < length; i++) {
1255                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
1256                        if (listener != null) {
1257                            try {
1258                                listener.onUidRulesChanged(uid, uidRules);
1259                            } catch (RemoteException e) {
1260                            }
1261                        }
1262                    }
1263                    mListeners.finishBroadcast();
1264                    return true;
1265                }
1266                case MSG_METERED_IFACES_CHANGED: {
1267                    final String[] meteredIfaces = (String[]) msg.obj;
1268                    final int length = mListeners.beginBroadcast();
1269                    for (int i = 0; i < length; i++) {
1270                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
1271                        if (listener != null) {
1272                            try {
1273                                listener.onMeteredIfacesChanged(meteredIfaces);
1274                            } catch (RemoteException e) {
1275                            }
1276                        }
1277                    }
1278                    mListeners.finishBroadcast();
1279                    return true;
1280                }
1281                default: {
1282                    return false;
1283                }
1284            }
1285        }
1286    };
1287
1288    private void setInterfaceQuota(String iface, long quotaBytes) {
1289        try {
1290            mNetworkManager.setInterfaceQuota(iface, quotaBytes);
1291        } catch (IllegalStateException e) {
1292            Slog.e(TAG, "problem setting interface quota", e);
1293        } catch (RemoteException e) {
1294            Slog.e(TAG, "problem setting interface quota", e);
1295        }
1296    }
1297
1298    private void removeInterfaceQuota(String iface) {
1299        try {
1300            mNetworkManager.removeInterfaceQuota(iface);
1301        } catch (IllegalStateException e) {
1302            Slog.e(TAG, "problem removing interface quota", e);
1303        } catch (RemoteException e) {
1304            Slog.e(TAG, "problem removing interface quota", e);
1305        }
1306    }
1307
1308    private void setInterfaceAlert(String iface, long alertBytes) {
1309        try {
1310            mNetworkManager.setInterfaceAlert(iface, alertBytes);
1311        } catch (IllegalStateException e) {
1312            Slog.e(TAG, "problem setting interface alert", e);
1313        } catch (RemoteException e) {
1314            Slog.e(TAG, "problem setting interface alert", e);
1315        }
1316    }
1317
1318    private void removeInterfaceAlert(String iface) {
1319        try {
1320            mNetworkManager.removeInterfaceAlert(iface);
1321        } catch (IllegalStateException e) {
1322            Slog.e(TAG, "problem removing interface alert", e);
1323        } catch (RemoteException e) {
1324            Slog.e(TAG, "problem removing interface alert", e);
1325        }
1326    }
1327
1328    private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
1329        try {
1330            mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
1331        } catch (IllegalStateException e) {
1332            Slog.e(TAG, "problem setting uid rules", e);
1333        } catch (RemoteException e) {
1334            Slog.e(TAG, "problem setting uid rules", e);
1335        }
1336    }
1337
1338    private String getActiveSubscriberId() {
1339        final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
1340                Context.TELEPHONY_SERVICE);
1341        return telephony.getSubscriberId();
1342    }
1343
1344    private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
1345        final Intent intent = new Intent();
1346        intent.setComponent(new ComponentName(
1347                "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity"));
1348        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1349        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
1350        return intent;
1351    }
1352
1353    private static Intent buildViewDataUsageIntent(NetworkTemplate template) {
1354        final Intent intent = new Intent();
1355        intent.setComponent(new ComponentName(
1356                "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
1357        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1358        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
1359        return intent;
1360    }
1361
1362    private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
1363        final int size = source.size();
1364        for (int i = 0; i < size; i++) {
1365            target.put(source.keyAt(i), true);
1366        }
1367    }
1368
1369    private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) {
1370        final int size = source.size();
1371        for (int i = 0; i < size; i++) {
1372            target.put(source.keyAt(i), true);
1373        }
1374    }
1375
1376    private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) {
1377        fout.print("[");
1378        final int size = value.size();
1379        for (int i = 0; i < size; i++) {
1380            fout.print(value.keyAt(i) + "=" + value.valueAt(i));
1381            if (i < size - 1) fout.print(",");
1382        }
1383        fout.print("]");
1384    }
1385
1386    private static int readIntAttribute(XmlPullParser in, String name) throws IOException {
1387        final String value = in.getAttributeValue(null, name);
1388        try {
1389            return Integer.parseInt(value);
1390        } catch (NumberFormatException e) {
1391            throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
1392        }
1393    }
1394
1395    private static long readLongAttribute(XmlPullParser in, String name) throws IOException {
1396        final String value = in.getAttributeValue(null, name);
1397        try {
1398            return Long.parseLong(value);
1399        } catch (NumberFormatException e) {
1400            throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
1401        }
1402    }
1403
1404    private static void writeIntAttribute(XmlSerializer out, String name, int value)
1405            throws IOException {
1406        out.attribute(null, name, Integer.toString(value));
1407    }
1408
1409    private static void writeLongAttribute(XmlSerializer out, String name, long value)
1410            throws IOException {
1411        out.attribute(null, name, Long.toString(value));
1412    }
1413
1414}
1415