Merge changes I3c19e008,I2c7c6013,I5cfd37d9 into lmp-dev

* changes:
  Update media session test application for new media router.
  Initial draft of new MediaRouter APIs.
  Delete first draft of media routing APIs.
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f1a2576..d20a5dc 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3751,6 +3751,48 @@
     /**
      * @hide Implement to provide correct calling token.
      */
+    public void startActivityForResultAsUser(Intent intent, int requestCode, UserHandle user) {
+        startActivityForResultAsUser(intent, requestCode, null, user);
+    }
+
+    /**
+     * @hide Implement to provide correct calling token.
+     */
+    public void startActivityForResultAsUser(Intent intent, int requestCode,
+            @Nullable Bundle options, UserHandle user) {
+        if (options != null) {
+            mActivityTransitionState.startExitOutTransition(this, options);
+        }
+        if (mParent != null) {
+            throw new RuntimeException("Can't be called from a child");
+        }
+        Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
+                this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode,
+                options, user);
+        if (ar != null) {
+            mMainThread.sendActivityResult(
+                mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData());
+        }
+        if (requestCode >= 0) {
+            // If this start is requesting a result, we can avoid making
+            // the activity visible until the result is received.  Setting
+            // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
+            // activity hidden during this time, to avoid flickering.
+            // This can only be done when a result is requested because
+            // that guarantees we will get information back when the
+            // activity is finished, no matter what happens to it.
+            mStartedActivity = true;
+        }
+
+        final View decor = mWindow != null ? mWindow.peekDecorView() : null;
+        if (decor != null) {
+            decor.cancelPendingInputEvents();
+        }
+    }
+
+    /**
+     * @hide Implement to provide correct calling token.
+     */
     public void startActivityAsUser(Intent intent, UserHandle user) {
         startActivityAsUser(intent, null, user);
     }
@@ -3760,7 +3802,7 @@
      */
     public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
         if (mParent != null) {
-            throw new RuntimeException("Called be called from a child");
+            throw new RuntimeException("Can't be called from a child");
         }
         Instrumentation.ActivityResult ar =
                 mInstrumentation.execStartActivity(
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index bae7ed7..3d53f9c 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -44,6 +44,7 @@
     <color name="qs_detail_empty">#24B0BEC5</color><!-- 14% blue grey 200-->
     <color name="data_usage_secondary">#99FFFFFF</color><!-- 60% white -->
     <color name="data_usage_graph_track">#33FFFFFF</color><!-- 20% white -->
+    <color name="data_usage_graph_warning">#FFFFFFFF</color>
     <color name="status_bar_clock_color">#33FFFFFF</color>
 
     <!-- Tint color for the content on the notification overflow card. -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6a7b450..b79dbbe 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -572,6 +572,8 @@
     <string name="quick_settings_cellular_detail_data_used"><xliff:g id="data_used" example="2.0 GB">%s</xliff:g> used</string>
     <!-- QuickSettings: Cellular detail panel, data limit format string [CHAR LIMIT=NONE] -->
     <string name="quick_settings_cellular_detail_data_limit"><xliff:g id="data_limit" example="2.0 GB">%s</xliff:g> limit</string>
+    <!-- QuickSettings: Cellular detail panel, data warning format string [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_cellular_detail_data_warning"><xliff:g id="data_limit" example="2.0 GB">%s</xliff:g> warning</string>
 
     <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
     <string name="recents_empty_message">No recent apps</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
index fa11af6..d55ceaa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
@@ -28,34 +28,34 @@
 
 public class DataUsageGraph extends View {
 
-    private final int mBackgroundColor;
     private final int mTrackColor;
     private final int mUsageColor;
     private final int mOverlimitColor;
+    private final int mWarningColor;
     private final int mMarkerWidth;
     private final RectF mTmpRect = new RectF();
     private final Paint mTmpPaint = new Paint();
 
-    private long mMaxLevel = 1;
     private long mLimitLevel;
     private long mWarningLevel;
     private long mUsageLevel;
+    private long mMaxLevel;
 
     public DataUsageGraph(Context context, AttributeSet attrs) {
         super(context, attrs);
         final Resources res = context.getResources();
-        mBackgroundColor = res.getColor(R.color.system_primary_color);
         mTrackColor = res.getColor(R.color.data_usage_graph_track);
         mUsageColor = res.getColor(R.color.system_accent_color);
         mOverlimitColor = res.getColor(R.color.system_warning_color);
+        mWarningColor = res.getColor(R.color.data_usage_graph_warning);
         mMarkerWidth = res.getDimensionPixelSize(R.dimen.data_usage_graph_marker_width);
     }
 
-    public void setLevels(long maxLevel, long limitLevel, long warningLevel, long usageLevel) {
-        mMaxLevel = Math.max(maxLevel, 1);
-        mLimitLevel = limitLevel;
-        mWarningLevel = warningLevel;
-        mUsageLevel = usageLevel;
+    public void setLevels(long limitLevel, long warningLevel, long usageLevel) {
+        mLimitLevel = Math.max(0, limitLevel);
+        mWarningLevel = Math.max(0, warningLevel);
+        mUsageLevel = Math.max(0, usageLevel);
+        mMaxLevel = Math.max(Math.max(Math.max(mLimitLevel, mWarningLevel), mUsageLevel), 1);
         postInvalidate();
     }
 
@@ -68,21 +68,22 @@
         final int w = getWidth();
         final int h = getHeight();
 
-        // draw track
-        r.set(0, 0, w, h);
-        p.setColor(mTrackColor);
-        canvas.drawRect(r, p);
-
-        final boolean hasLimit = mLimitLevel > 0;
-        final boolean overLimit = hasLimit && mUsageLevel > mLimitLevel;
-
-        final long maxLevel = hasLimit ? Math.max(mUsageLevel, mLimitLevel) : mMaxLevel;
-        final long usageLevel = hasLimit ? Math.min(mUsageLevel, mLimitLevel) : mUsageLevel;
-        float usageRight = w * (usageLevel / (float) maxLevel);
+        final boolean overLimit = mLimitLevel > 0 && mUsageLevel > mLimitLevel;
+        float usageRight = w * (mUsageLevel / (float) mMaxLevel);
         if (overLimit) {
-            usageRight -= (mMarkerWidth / 2);
-            usageRight = Math.min(usageRight, w - mMarkerWidth * 2);
-            usageRight = Math.max(usageRight, mMarkerWidth);
+            // compute the gap
+            usageRight = w * (mLimitLevel / (float) mMaxLevel) - (mMarkerWidth / 2);
+            usageRight = Math.min(Math.max(usageRight, mMarkerWidth), w - mMarkerWidth * 2);
+
+            // draw overlimit
+            r.set(usageRight + mMarkerWidth, 0, w, h);
+            p.setColor(mOverlimitColor);
+            canvas.drawRect(r, p);
+        } else {
+            // draw track
+            r.set(0, 0, w, h);
+            p.setColor(mTrackColor);
+            canvas.drawRect(r, p);
         }
 
         // draw usage
@@ -90,16 +91,11 @@
         p.setColor(mUsageColor);
         canvas.drawRect(r, p);
 
-        if (overLimit) {
-            // draw gap
-            r.set(usageRight, 0, usageRight + mMarkerWidth, h);
-            p.setColor(mBackgroundColor);
-            canvas.drawRect(r, p);
-
-            // draw overlimit
-            r.set(usageRight + mMarkerWidth, 0, w, h);
-            p.setColor(mOverlimitColor);
-            canvas.drawRect(r, p);
-        }
+        // draw warning marker
+        float warningLeft = w * (mWarningLevel / (float) mMaxLevel) - mMarkerWidth / 2;
+        warningLeft = Math.min(Math.max(warningLeft, 0), w - mMarkerWidth);
+        r.set(warningLeft, 0, warningLeft + mMarkerWidth, h);
+        p.setColor(mWarningColor);
+        canvas.drawRect(r, p);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 1f12b2a..d76a2fe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -216,21 +216,27 @@
             final DataUsageInfo info = mController.getDataUsageInfo();
             if (info == null) return v;
             final Resources res = mContext.getResources();
-            int titleId;
-            long bytes;
+            final int titleId;
+            final long bytes;
             int usageColor = R.color.system_accent_color;
-            String top = null, bottom = null;
-            if (info.limitLevel <= 0) { // no limit
+            final String top;
+            String bottom = null;
+            if (info.usageLevel < info.warningLevel || info.limitLevel <= 0) {
+                // under warning, or no limit
                 titleId = R.string.quick_settings_cellular_detail_data_usage;
                 bytes = info.usageLevel;
-            } else if (info.usageLevel <= info.limitLevel) { // under limit
+                top = res.getString(R.string.quick_settings_cellular_detail_data_warning,
+                        formatBytes(info.warningLevel));
+            } else if (info.usageLevel <= info.limitLevel) {
+                // over warning, under limit
                 titleId = R.string.quick_settings_cellular_detail_remaining_data;
                 bytes = info.limitLevel - info.usageLevel;
                 top = res.getString(R.string.quick_settings_cellular_detail_data_used,
                         formatBytes(info.usageLevel));
                 bottom = res.getString(R.string.quick_settings_cellular_detail_data_limit,
                         formatBytes(info.limitLevel));
-            } else { // over limit
+            } else {
+                // over limit
                 titleId = R.string.quick_settings_cellular_detail_over_limit;
                 bytes = info.usageLevel - info.limitLevel;
                 top = res.getString(R.string.quick_settings_cellular_detail_data_used,
@@ -246,7 +252,7 @@
             usage.setText(formatBytes(bytes));
             usage.setTextColor(res.getColor(usageColor));
             final DataUsageGraph graph = (DataUsageGraph) v.findViewById(R.id.usage_graph);
-            graph.setLevels(info.maxLevel, info.limitLevel, info.warningLevel, info.usageLevel);
+            graph.setLevels(info.limitLevel, info.warningLevel, info.usageLevel);
             final TextView carrier = (TextView) v.findViewById(R.id.usage_carrier_text);
             carrier.setText(info.carrier);
             final TextView period = (TextView) v.findViewById(R.id.usage_period_text);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java
index f2dfe05..33d68bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java
@@ -20,6 +20,8 @@
 import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
 import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
 import static android.telephony.TelephonyManager.SIM_STATE_READY;
+import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
+import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
 
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -33,19 +35,23 @@
 import android.os.ServiceManager;
 import android.telephony.TelephonyManager;
 import android.text.format.DateUtils;
+import android.text.format.Time;
 import android.util.Log;
 
 import com.android.systemui.statusbar.policy.NetworkController.DataUsageInfo;
 
-import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Locale;
 
 public class MobileDataController {
     private static final String TAG = "MobileDataController";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private static final SimpleDateFormat MMM_D = new SimpleDateFormat("MMM d");
+    private static final long DEFAULT_WARNING_LEVEL = 2L * 1024 * 1024 * 1024;
     private static final int FIELDS = FIELD_RX_BYTES | FIELD_TX_BYTES;
+    private static final StringBuilder PERIOD_BUILDER = new StringBuilder(50);
+    private static final java.util.Formatter PERIOD_FORMATTER = new java.util.Formatter(
+            PERIOD_BUILDER, Locale.getDefault());
 
     private final Context mContext;
     private final TelephonyManager mTelephonyManager;
@@ -87,6 +93,13 @@
         return null;
     }
 
+    private static Time addMonth(Time t, int months) {
+        final Time rt = new Time(t);
+        rt.set(t.monthDay, t.month + months, t.year);
+        rt.normalize(false);
+        return rt;
+    }
+
     public DataUsageInfo getDataUsageInfo() {
         final String subscriberId = getActiveSubscriberId(mContext);
         if (subscriberId == null) {
@@ -101,9 +114,28 @@
         try {
             final NetworkStatsHistory history = mSession.getHistoryForNetwork(template, FIELDS);
             final long now = System.currentTimeMillis();
-            // period = last 4 wks for now
-            final long start = now - DateUtils.WEEK_IN_MILLIS * 4;
-            final long end = now;
+            final long start, end;
+            if (policy != null && policy.cycleDay > 0) {
+                // period = determined from cycleDay
+                if (DEBUG) Log.d(TAG, "Cycle day=" + policy.cycleDay + " tz="
+                        + policy.cycleTimezone);
+                final Time nowTime = new Time(policy.cycleTimezone);
+                nowTime.setToNow();
+                final Time policyTime = new Time(nowTime);
+                policyTime.set(policy.cycleDay, policyTime.month, policyTime.year);
+                policyTime.normalize(false);
+                if (nowTime.after(policyTime)) {
+                    start = policyTime.toMillis(false);
+                    end = addMonth(policyTime, 1).toMillis(false);
+                } else {
+                    start = addMonth(policyTime, -1).toMillis(false);
+                    end = policyTime.toMillis(false);
+                }
+            } else {
+                // period = last 4 wks
+                end = now;
+                start = now - DateUtils.WEEK_IN_MILLIS * 4;
+            }
             final long callStart = System.currentTimeMillis();
             final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
             final long callEnd = System.currentTimeMillis();
@@ -115,12 +147,13 @@
             }
             final long totalBytes = entry.rxBytes + entry.txBytes;
             final DataUsageInfo usage = new DataUsageInfo();
-            usage.maxLevel = (long) (totalBytes / .4);
             usage.usageLevel = totalBytes;
-            usage.period = MMM_D.format(new Date(start)) + " - " + MMM_D.format(new Date(end));
+            usage.period = formatDateRange(start, end);
             if (policy != null) {
                 usage.limitLevel = policy.limitBytes > 0 ? policy.limitBytes : 0;
                 usage.warningLevel = policy.warningBytes > 0 ? policy.warningBytes : 0;
+            } else {
+                usage.warningLevel = DEFAULT_WARNING_LEVEL;
             }
             return usage;
         } catch (RemoteException e) {
@@ -178,6 +211,15 @@
         return actualSubscriberId;
     }
 
+    private String formatDateRange(long start, long end) {
+        final int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH;
+        synchronized (PERIOD_BUILDER) {
+            PERIOD_BUILDER.setLength(0);
+            return DateUtils.formatDateRange(mContext, PERIOD_FORMATTER, start, end, flags, null)
+                    .toString();
+        }
+    }
+
     public interface Callback {
         void onMobileDataEnabled(boolean enabled);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index d058bd0..6d8b400 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -61,7 +61,6 @@
     public static class DataUsageInfo {
         public String carrier;
         public String period;
-        public long maxLevel;
         public long limitLevel;
         public long warningLevel;
         public long usageLevel;