ThrottleService.java revision 9e696c29f06d45d2891e1d38fd8d9033a9e21bb9
19e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt/*
29e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * Copyright (C) 2007 The Android Open Source Project
39e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt *
49e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
59e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * you may not use this file except in compliance with the License.
69e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * You may obtain a copy of the License at
79e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt *
89e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt *      http://www.apache.org/licenses/LICENSE-2.0
99e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt *
109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * Unless required by applicable law or agreed to in writing, software
119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * See the License for the specific language governing permissions and
149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * limitations under the License.
159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt */
169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltpackage com.android.server;
189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.app.AlarmManager;
209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.app.Notification;
219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.app.NotificationManager;
229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.app.PendingIntent;
239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.app.Service;
249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.BroadcastReceiver;
259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.Context;
269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.Intent;
279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.IntentFilter;
289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.pm.PackageManager;
299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.res.Resources;
309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.SharedPreferences;
319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.net.IThrottleManager;
329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.net.ThrottleManager;
339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.Binder;
349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.Handler;
359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.HandlerThread;
369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.IBinder;
379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.INetworkManagementService;
389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.Looper;
399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.Message;
409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.RemoteException;
419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.ServiceManager;
429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.SystemClock;
439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.SystemProperties;
449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.provider.Settings;
459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.util.Slog;
469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.io.FileDescriptor;
489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.io.PrintWriter;
499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.util.Calendar;
509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.util.GregorianCalendar;
519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.util.Random;
529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt// TODO - add comments - reference the ThrottleManager for public API
549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltpublic class ThrottleService extends IThrottleManager.Stub {
559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String TESTING_ENABLED_PROPERTY = "persist.throttle.testing";
579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String TAG = "ThrottleService";
599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static boolean DBG = true;
609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private Handler mHandler;
619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private HandlerThread mThread;
629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private Context mContext;
649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private int mPolicyPollPeriodSec;
669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int DEFAULT_POLLING_PERIOD_SEC = 60 * 10;
679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int TESTING_POLLING_PERIOD_SEC = 60 * 1;
689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int TESTING_RESET_PERIOD_SEC = 60 * 3;
709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int PERIOD_COUNT = 6;
729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private long mPolicyThreshold;
749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // TODO - remove testing stuff?
759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final long DEFAULT_TESTING_THRESHOLD = 1 * 1024 * 1024;
769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final long DEFAULT_THRESHOLD = 0; // off by default
779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private int mPolicyThrottleValue;
799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int DEFAULT_THROTTLE_VALUE = 100; // 100 Kbps
809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private int mPolicyResetDay; // 1-28
829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private long mLastRead; // read byte count from last poll
849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private long mLastWrite; // write byte count from last poll
859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String ACTION_POLL = "com.android.server.ThrottleManager.action.POLL";
879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static int POLL_REQUEST = 0;
889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private PendingIntent mPendingPollIntent;
899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String ACTION_RESET = "com.android.server.ThorottleManager.action.RESET";
909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static int RESET_REQUEST = 1;
919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private PendingIntent mPendingResetIntent;
929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private INetworkManagementService mNMService;
949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private AlarmManager mAlarmManager;
959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private NotificationManager mNotificationManager;
969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private DataRecorder mRecorder;
989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private int mThrottleLevel; // 0 for none, 1 for first throttle val, 2 for next, etc
1009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private String mPolicyIface;
1029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int NOTIFICATION_WARNING   = 2;
1049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int NOTIFICATION_ALL       = 0xFFFFFFFF;
1059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private int mPolicyNotificationsAllowedMask;
1069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private Notification mThrottlingNotification;
1089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private boolean mWarningNotificationSent = false;
1099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public ThrottleService(Context context) {
1119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        if (DBG) Slog.d(TAG, "Starting ThrottleService");
1129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext = context;
1139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
1159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Intent pollIntent = new Intent(ACTION_POLL, null);
1169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
1179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Intent resetIntent = new Intent(ACTION_RESET, null);
1189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mPendingResetIntent = PendingIntent.getBroadcast(mContext, RESET_REQUEST, resetIntent, 0);
1199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mNMService = INetworkManagementService.Stub.asInterface(b);
1229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mNotificationManager = (NotificationManager)mContext.getSystemService(
1249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Context.NOTIFICATION_SERVICE);
1259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
1269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private void enforceAccessPermission() {
1289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
1299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                android.Manifest.permission.ACCESS_NETWORK_STATE,
1309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                "ThrottleService");
1319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
1329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized long getResetTime(String iface) {
1349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
1359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        if (iface.equals(mPolicyIface) && (mRecorder != null)) mRecorder.getPeriodEnd();
1369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
1379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
1389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized long getPeriodStartTime(String iface) {
1399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
1409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        if (iface.equals(mPolicyIface) && (mRecorder != null)) mRecorder.getPeriodStart();
1419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
1429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
1439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    //TODO - a better name?  getCliffByteCountThreshold?
1449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized long getCliffThreshold(String iface, int cliff) {
1459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
1469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        if ((cliff == 0) && iface.equals(mPolicyIface)) {
1479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return mPolicyThreshold;
1489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
1499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
1509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
1519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // TODO - a better name? getThrottleRate?
1529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized int getCliffLevel(String iface, int cliff) {
1539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
1549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        if ((cliff == 0) && iface.equals(mPolicyIface)) {
1559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return mPolicyThrottleValue;
1569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
1579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
1589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
1599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized long getByteCount(String iface, int dir, int period, int ago) {
1619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
1629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        if (iface.equals(mPolicyIface) &&
1639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                (period == ThrottleManager.PERIOD_CYCLE) &&
1649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                (mRecorder != null)) {
1659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (dir == ThrottleManager.DIRECTION_TX) return mRecorder.getPeriodTx(ago);
1669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (dir == ThrottleManager.DIRECTION_RX) return mRecorder.getPeriodRx(ago);
1679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
1689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
1699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
1709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // TODO - a better name - getCurrentThrottleRate?
1729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized int getThrottle(String iface) {
1739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
1749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        if (iface.equals(mPolicyIface) && (mThrottleLevel == 1)) {
1759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return mPolicyThrottleValue;
1769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
1779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
1789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
1799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    void systemReady() {
1819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        if (DBG) Slog.d(TAG, "systemReady");
1829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext.registerReceiver(
1839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            new BroadcastReceiver() {
1849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                @Override
1859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                public void onReceive(Context context, Intent intent) {
1869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mHandler.obtainMessage(EVENT_POLL_ALARM).sendToTarget();
1879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
1889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }, new IntentFilter(ACTION_POLL));
1899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext.registerReceiver(
1919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            new BroadcastReceiver() {
1929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                @Override
1939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                public void onReceive(Context context, Intent intent) {
1949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget();
1959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
1969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }, new IntentFilter(ACTION_RESET));
1979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        // use a new thread as we don't want to stall the system for file writes
1999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mThread = new HandlerThread(TAG);
2009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mThread.start();
2019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mHandler = new MyHandler(mThread.getLooper());
2029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mHandler.obtainMessage(EVENT_REBOOT_RECOVERY).sendToTarget();
2039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
2049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_REBOOT_RECOVERY = 0;
2079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_POLICY_CHANGED  = 1;
2089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_POLL_ALARM      = 2;
2099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_RESET_ALARM     = 3;
2109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private class MyHandler extends Handler {
2119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public MyHandler(Looper l) {
2129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            super(l);
2139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
2149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        @Override
2169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public void handleMessage(Message msg) {
2179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            switch (msg.what) {
2189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_REBOOT_RECOVERY:
2199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onRebootRecovery();
2209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                break;
2219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_POLICY_CHANGED:
2229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onPolicyChanged();
2239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                break;
2249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_POLL_ALARM:
2259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onPollAlarm();
2269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                break;
2279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_RESET_ALARM:
2289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onResetAlarm();
2299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
2309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
2319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onRebootRecovery() {
2339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (DBG) Slog.d(TAG, "onRebootRecovery");
2349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // check for sim change TODO
2359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // reregister for notification of policy change
2369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // register for roaming indication change
2389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // check for roaming TODO
2399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mRecorder = new DataRecorder(mContext, ThrottleService.this);
2419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // get policy
2439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mHandler.obtainMessage(EVENT_POLICY_CHANGED).sendToTarget();
2449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // evaluate current conditions
2469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mHandler.obtainMessage(EVENT_POLL_ALARM).sendToTarget();
2479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
2489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onSimChange() {
2509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO
2519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
2529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        // check for new policy info (threshold limit/value/etc)
2549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onPolicyChanged() {
2559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            boolean testing = SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true");
2569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            int pollingPeriod = DEFAULT_POLLING_PERIOD_SEC;
2589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (testing) pollingPeriod = TESTING_POLLING_PERIOD_SEC;
2599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mPolicyPollPeriodSec = Settings.Secure.getInt(mContext.getContentResolver(),
2609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Settings.Secure.THROTTLE_POLLING_SEC, pollingPeriod);
2619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - remove testing stuff?
2639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long defaultThreshold = DEFAULT_THRESHOLD;
2649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (testing) defaultThreshold = DEFAULT_TESTING_THRESHOLD;
2659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (ThrottleService.this) {
2669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPolicyThreshold = Settings.Secure.getLong(mContext.getContentResolver(),
2679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        Settings.Secure.THROTTLE_THRESHOLD, defaultThreshold);
2689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPolicyThrottleValue = Settings.Secure.getInt(mContext.getContentResolver(),
2699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        Settings.Secure.THROTTLE_VALUE, DEFAULT_THROTTLE_VALUE);
2709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
2719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mPolicyResetDay = Settings.Secure.getInt(mContext.getContentResolver(),
2729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Settings.Secure.THROTTLE_RESET_DAY, -1);
2739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (mPolicyResetDay == -1 ||
2749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    ((mPolicyResetDay < 1) || (mPolicyResetDay > 28))) {
2759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Random g = new Random();
2769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPolicyResetDay = 1 + g.nextInt(28); // 1-28
2779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Settings.Secure.putInt(mContext.getContentResolver(),
2789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Settings.Secure.THROTTLE_RESET_DAY, mPolicyResetDay);
2799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
2809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (ThrottleService.this) {
2819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPolicyIface = Settings.Secure.getString(mContext.getContentResolver(),
2829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        Settings.Secure.THROTTLE_IFACE);
2839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                // TODO - read default from resource so it's device-specific
2849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (mPolicyIface == null) mPolicyIface = "rmnet0";
2859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
2869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mPolicyNotificationsAllowedMask = Settings.Secure.getInt(mContext.getContentResolver(),
2889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Settings.Secure.THROTTLE_NOTIFICATION_TYPE, NOTIFICATION_ALL);
2899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Slog.d(TAG, "onPolicyChanged testing=" + testing +", period=" + mPolicyPollPeriodSec +
2919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    ", threshold=" + mPolicyThreshold + ", value=" + mPolicyThrottleValue +
2929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    ", resetDay=" + mPolicyResetDay + ", noteType=" +
2939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPolicyNotificationsAllowedMask);
2949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Calendar end = calculatePeriodEnd();
2969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Calendar start = calculatePeriodStart(end);
2979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mRecorder.setNextPeriod(start,end);
2999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mAlarmManager.cancel(mPendingResetIntent);
3019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mAlarmManager.set(AlarmManager.RTC_WAKEUP, end.getTimeInMillis(),
3029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPendingResetIntent);
3039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
3049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onPollAlarm() {
3069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long now = SystemClock.elapsedRealtime();
3079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long next = now + mPolicyPollPeriodSec*1000;
3089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long incRead = 0;
3099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long incWrite = 0;
3109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            try {
3119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                incRead = mNMService.getInterfaceRxCounter(mPolicyIface) - mLastRead;
3129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                incWrite = mNMService.getInterfaceTxCounter(mPolicyIface) - mLastWrite;
3139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            } catch (RemoteException e) {
3149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Slog.e(TAG, "got remoteException in onPollAlarm:" + e);
3159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
3169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mRecorder.addData(incRead, incWrite);
3189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long periodRx = mRecorder.getPeriodRx(0);
3209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long periodTx = mRecorder.getPeriodTx(0);
3219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long total = periodRx + periodTx;
3229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (DBG) {
3239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Slog.d(TAG, "onPollAlarm - now =" + now + ", read =" + incRead +
3249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        ", written =" + incWrite + ", new total =" + total);
3259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
3269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mLastRead += incRead;
3279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mLastWrite += incWrite;
3289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            checkThrottleAndPostNotification(total);
3309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Intent broadcast = new Intent(ThrottleManager.THROTTLE_POLL_ACTION);
3329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_READ, periodRx);
3339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_WRITE, periodTx);
3349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_START, mRecorder.getPeriodStart());
3359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_END, mRecorder.getPeriodEnd());
3369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mContext.sendStickyBroadcast(broadcast);
3379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, next, mPendingPollIntent);
3399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
3409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void checkThrottleAndPostNotification(long currentTotal) {
3429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // are we even doing this?
3439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (mPolicyThreshold == 0)
3449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return;
3459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // check if we need to throttle
3479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (currentTotal > mPolicyThreshold) {
3489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (mThrottleLevel != 1) {
3499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    synchronized (ThrottleService.this) {
3509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        mThrottleLevel = 1;
3519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    }
3529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    if (DBG) Slog.d(TAG, "Threshold " + mPolicyThreshold + " exceeded!");
3539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    try {
3549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        mNMService.setInterfaceThrottle(mPolicyIface,
3559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                                mPolicyThrottleValue, mPolicyThrottleValue);
3569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    } catch (Exception e) {
3579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        Slog.e(TAG, "error setting Throttle: " + e);
3589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    }
3599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mNotificationManager.cancel(com.android.internal.R.drawable.
3619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                            stat_sys_throttle_warning);
3629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    postNotification(com.android.internal.R.string.throttled_notification_title,
3649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                            com.android.internal.R.string.throttled_notification_message,
3659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                            com.android.internal.R.drawable.stat_sys_throttled);
3669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
3689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, mPolicyThrottleValue);
3699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mContext.sendStickyBroadcast(broadcast);
3709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                } // else already up!
3729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            } else {
3739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if ((mPolicyNotificationsAllowedMask & NOTIFICATION_WARNING) != 0) {
3749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    // check if we should warn about throttle
3759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    if (currentTotal > (mPolicyThreshold/2) && !mWarningNotificationSent) {
3769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        mWarningNotificationSent = true;
3779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        mNotificationManager.cancel(com.android.internal.R.drawable.
3789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                                stat_sys_throttle_warning);
3799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        postNotification(com.android.internal.R.string.
3809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                                throttle_warning_notification_title,
3819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                                com.android.internal.R.string.
3829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                                throttle_warning_notification_message,
3839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                                com.android.internal.R.drawable.stat_sys_throttle_warning);
3849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    } else {
3859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        mWarningNotificationSent =false;
3869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    }
3879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
3889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
3899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
3909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void postNotification(int titleInt, int messageInt, int icon) {
3929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Intent intent = new Intent();
3939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - fix up intent
3949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
3959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
3969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
3989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Resources r = Resources.getSystem();
4009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            CharSequence title = r.getText(titleInt);
4019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            CharSequence message = r.getText(messageInt);
4029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (mThrottlingNotification == null) {
4039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification = new Notification();
4049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification.when = 0;
4059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                // TODO -  fixup icon
4069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification.icon = icon;
4079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification.defaults &= ~Notification.DEFAULT_SOUND;
4089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt//                mThrottlingNotification.flags = Notification.FLAG_ONGOING_EVENT;
4099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mThrottlingNotification.tickerText = title;
4119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mThrottlingNotification.setLatestEventInfo(mContext, title, message, pi);
4129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mNotificationManager.notify(mThrottlingNotification.icon, mThrottlingNotification);
4149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
4159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private synchronized void clearThrottleAndNotification() {
4189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (mThrottleLevel == 1) {
4199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                synchronized (ThrottleService.this) {
4209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mThrottleLevel = 0;
4219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
4229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                try {
4239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mNMService.setInterfaceThrottle(mPolicyIface, -1, -1);
4249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                } catch (Exception e) {
4259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Slog.e(TAG, "error clearing Throttle: " + e);
4269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
4279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
4289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, -1);
4299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mContext.sendStickyBroadcast(broadcast);
4309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mNotificationManager.cancel(com.android.internal.R.drawable.stat_sys_throttle_warning);
4329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mNotificationManager.cancel(com.android.internal.R.drawable.stat_sys_throttled);
4339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mWarningNotificationSent = false;
4349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
4359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private Calendar calculatePeriodEnd() {
4379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Calendar end = GregorianCalendar.getInstance();
4389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            int day = end.get(Calendar.DAY_OF_MONTH);
4399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            end.set(Calendar.DAY_OF_MONTH, mPolicyResetDay);
4409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            end.set(Calendar.HOUR_OF_DAY, 0);
4419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            end.set(Calendar.MINUTE, 0);
4429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (day >= mPolicyResetDay) {
4439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                int month = end.get(Calendar.MONTH);
4449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (month == Calendar.DECEMBER) {
4459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    end.set(Calendar.YEAR, end.get(Calendar.YEAR) + 1);
4469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    month = Calendar.JANUARY - 1;
4479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
4489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                end.set(Calendar.MONTH, month + 1);
4499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - remove!
4529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true")) {
4539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                end = GregorianCalendar.getInstance();
4549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                end.add(Calendar.SECOND, TESTING_RESET_PERIOD_SEC);
4559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return end;
4579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
4589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private Calendar calculatePeriodStart(Calendar end) {
4599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Calendar start = (Calendar)end.clone();
4609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            int month = end.get(Calendar.MONTH);
4619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (end.get(Calendar.MONTH) == Calendar.JANUARY) {
4629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                month = Calendar.DECEMBER + 1;
4639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                start.set(Calendar.YEAR, start.get(Calendar.YEAR) - 1);
4649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            start.set(Calendar.MONTH, month - 1);
4669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - remove!!
4689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true")) {
4699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                start = (Calendar)end.clone();
4709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                start.add(Calendar.SECOND, -TESTING_RESET_PERIOD_SEC);
4719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return start;
4739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
4749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onResetAlarm() {
4769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (DBG) {
4779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Slog.d(TAG, "onResetAlarm - last period had " + mRecorder.getPeriodRx(0) +
4789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        " bytes read and " + mRecorder.getPeriodTx(0) + " written");
4799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Calendar end = calculatePeriodEnd();
4829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Calendar start = calculatePeriodStart(end);
4839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            clearThrottleAndNotification();
4859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mRecorder.setNextPeriod(start,end);
4879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mAlarmManager.set(AlarmManager.RTC_WAKEUP, end.getTimeInMillis(),
4899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPendingResetIntent);
4909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
4919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
4929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // records bytecount data for a given time and accumulates it into larger time windows
4949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // for logging and other purposes
4959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    //
4969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // since time can be changed (user or network action) we will have to track the time of the
4979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // last recording and deal with it.
4989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static class DataRecorder {
4999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long[] mPeriodRxData;
5009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long[] mPeriodTxData;
5019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        int mCurrentPeriod;
5029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        int mPeriodCount;
5039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Calendar mPeriodStart;
5059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Calendar mPeriodEnd;
5069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        ThrottleService mParent;
5089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Context mContext;
5099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        SharedPreferences mSharedPreferences;
5109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        DataRecorder(Context context, ThrottleService parent) {
5129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mContext = context;
5139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mParent = parent;
5149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
5169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodCount = 6;
5179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodRxData = new long[mPeriodCount];
5189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodTxData = new long[mPeriodCount];
5199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodStart = Calendar.getInstance();
5219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodEnd = Calendar.getInstance();
5229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mSharedPreferences = mContext.getSharedPreferences("ThrottleData",
5249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        android.content.Context.MODE_PRIVATE);
5259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                zeroData(0);
5279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                retrieve();
5289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
5299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
5309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        void setNextPeriod(Calendar start, Calendar end) {
5329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (DBG) {
5339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Slog.d(TAG, "setting next period to " + start.getTimeInMillis() +
5349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        " --until-- " + end.getTimeInMillis());
5359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
5369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // if we roll back in time to a previous period, toss out the current data
5379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // if we roll forward to the next period, advance to the next
5389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (end.before(mPeriodStart)) {
5409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (DBG) {
5419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Slog.d(TAG, " old start was " + mPeriodStart.getTimeInMillis() + ", wiping");
5429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
5439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                synchronized (mParent) {
5449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodRxData[mCurrentPeriod] = 0;
5459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodTxData[mCurrentPeriod] = 0;
5469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
5479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            } else if(start.after(mPeriodEnd)) {
5489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (DBG) {
5499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Slog.d(TAG, " old end was " + mPeriodEnd.getTimeInMillis() + ", following");
5509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
5519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                synchronized (mParent) {
5529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    ++mCurrentPeriod;
5539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    if (mCurrentPeriod >= mPeriodCount) mCurrentPeriod = 0;
5549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodRxData[mCurrentPeriod] = 0;
5559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodTxData[mCurrentPeriod] = 0;
5569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
5579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            } else {
5589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (DBG) Slog.d(TAG, " we fit - ammending to last period");
5599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
5609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            setPeriodStart(start);
5619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            setPeriodEnd(end);
5629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            record();
5639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
5649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public long getPeriodEnd() {
5669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
5679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodEnd.getTimeInMillis();
5689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
5699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
5709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void setPeriodEnd(Calendar end) {
5729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
5739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodEnd = end;
5749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
5759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
5769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public long getPeriodStart() {
5789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
5799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodStart.getTimeInMillis();
5809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
5819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
5829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void setPeriodStart(Calendar start) {
5849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
5859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodStart = start;
5869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
5879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
5889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public int getPeriodCount() {
5909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
5919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodCount;
5929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
5939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
5949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void zeroData(int field) {
5969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
5979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                for(int period = 0; period<mPeriodCount; period++) {
5989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodRxData[period] = 0;
5999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodTxData[period] = 0;
6009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
6019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mCurrentPeriod = 0;
6029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        // if time moves backward accumulate all read/write that's lost into the now
6079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        // otherwise time moved forward.
6089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        void addData(long bytesRead, long bytesWritten) {
6099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
6109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodRxData[mCurrentPeriod] += bytesRead;
6119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodTxData[mCurrentPeriod] += bytesWritten;
6129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            record();
6149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void record() {
6179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // serialize into a secure setting
6189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 1 int mPeriodCount
6209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13*6 long[PERIOD_COUNT] mPeriodRxData
6219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13*6 long[PERIOD_COUNT] mPeriodTxData
6229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 1  int mCurrentPeriod
6239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13 long periodStartMS
6249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13 long periodEndMS
6259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 199 chars max
6269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            StringBuilder builder = new StringBuilder();
6279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mPeriodCount);
6289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(":");
6299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            for(int i=0; i < mPeriodCount; i++) {
6309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(mPeriodRxData[i]);
6319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(":");
6329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            for(int i=0; i < mPeriodCount; i++) {
6349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(mPeriodTxData[i]);
6359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(":");
6369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mCurrentPeriod);
6389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(":");
6399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mPeriodStart.getTimeInMillis());
6409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(":");
6419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mPeriodEnd.getTimeInMillis());
6429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(":");
6439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            SharedPreferences.Editor editor = mSharedPreferences.edit();
6459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            editor.putString("Data", builder.toString());
6479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            editor.commit();
6489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void retrieve() {
6519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            String data = mSharedPreferences.getString("Data", "");
6529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt//            String data = Settings.Secure.getString(mContext.getContentResolver(),
6539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt//                    Settings.Secure.THROTTLE_VALUE);
6549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (data == null || data.length() == 0) return;
6559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
6579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                String[] parsed = data.split(":");
6589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                int parsedUsed = 0;
6599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (parsed.length < 6) return;
6609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodCount = Integer.parseInt(parsed[parsedUsed++]);
6629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (parsed.length != 4 + (2 * mPeriodCount)) return;
6639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodRxData = new long[mPeriodCount];
6659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                for(int i=0; i < mPeriodCount; i++) {
6669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodRxData[i] = Long.parseLong(parsed[parsedUsed++]);
6679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
6689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodTxData = new long[mPeriodCount];
6699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                for(int i=0; i < mPeriodCount; i++) {
6709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodTxData[i] = Long.parseLong(parsed[parsedUsed++]);
6719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
6729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mCurrentPeriod = Integer.parseInt(parsed[parsedUsed++]);
6739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodStart = new GregorianCalendar();
6749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodStart.setTimeInMillis(Long.parseLong(parsed[parsedUsed++]));
6759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodEnd = new GregorianCalendar();
6769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodEnd.setTimeInMillis(Long.parseLong(parsed[parsedUsed++]));
6779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long getPeriodRx(int which) {
6819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (DBG) { // TODO - remove
6829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Slog.d(TAG, "reading slot "+ which +" with current =" + mCurrentPeriod);
6839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                for(int x = 0; x<mPeriodCount; x++) {
6849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Slog.d(TAG, "  " + x + " = " + mPeriodRxData[x]);
6859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
6869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
6889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which > mPeriodCount) return 0;
6899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                which = mCurrentPeriod - which;
6909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which < 0) which += mPeriodCount;
6919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodRxData[which];
6929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long getPeriodTx(int which) {
6959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
6969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which > mPeriodCount) return 0;
6979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                which = mCurrentPeriod - which;
6989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which < 0) which += mPeriodCount;
6999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodTxData[which];
7009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
7019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
7029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
7039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    @Override
7059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
7069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        if (mContext.checkCallingOrSelfPermission(
7079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                android.Manifest.permission.DUMP)
7089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                != PackageManager.PERMISSION_GRANTED) {
7099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            pw.println("Permission Denial: can't dump ThrottleService " +
7109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    "from from pid=" + Binder.getCallingPid() + ", uid=" +
7119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Binder.getCallingUid());
7129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return;
7139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
7149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        pw.println();
7159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        pw.println("The threshold is " + mPolicyThreshold +
7179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                ", after which you experince throttling to " +
7189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPolicyThrottleValue + "kbps");
7199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        pw.println("Current period is " +
7209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                (mRecorder.getPeriodEnd() - mRecorder.getPeriodStart())/1000 + " seconds long " +
7219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                "and ends in " + (mRecorder.getPeriodEnd() - System.currentTimeMillis()) / 1000 +
7229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                " seconds.");
7239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        pw.println("Polling every " + mPolicyPollPeriodSec + " seconds");
7249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        for (int i = 0; i < mRecorder.getPeriodCount(); i++) {
7259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            pw.println(" Period[" + i + "] - read:" + mRecorder.getPeriodRx(i) + ", written:" +
7269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mRecorder.getPeriodTx(i));
7279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
7289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
7299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt}
730