Merge "Add DHCP error event class and record DHCP errors." into nyc-dev
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index ddf90a8..8c73e6a 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -3599,10 +3599,20 @@
/**
* <p>The shading map is a low-resolution floating-point map
- * that lists the coefficients used to correct for vignetting, for each
- * Bayer color channel of RAW image data.</p>
- * <p>The least shaded section of the image should have a gain factor
- * of 1; all other sections should have gains above 1.</p>
+ * that lists the coefficients used to correct for vignetting and color shading,
+ * for each Bayer color channel of RAW image data.</p>
+ * <p>The lens shading correction is defined as a full shading correction that
+ * corrects both color shading for the output non-RAW images. After the
+ * shading map is applied, the output non-RAW images will be flat-field images
+ * for flat scenes under uniform illumination.</p>
+ * <p>When there is no lens shading correction applied to RAW output images
+ * ({@link CameraCharacteristics#SENSOR_INFO_LENS_SHADING_APPLIED android.sensor.info.lensShadingApplied} <code>==</code> false), this map is a full lens
+ * shading correction map; when there is some lens shading correction applied
+ * to the RAW output image ({@link CameraCharacteristics#SENSOR_INFO_LENS_SHADING_APPLIED android.sensor.info.lensShadingApplied} <code>==</code> true),
+ * this map reports the remaining lens shading correction map that needs to be
+ * applied to get fully shading corrected images.</p>
+ * <p>For a full shading correction map, the least shaded section of the image
+ * should have a gain factor of 1; all other sections should have gains above 1.</p>
* <p>When {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} = TRANSFORM_MATRIX, the map
* must take into account the colorCorrection settings.</p>
* <p>The shading map is for the entire active pixel array, and is not
diff --git a/core/java/android/net/metrics/ConnectivityServiceChangeEvent.java b/core/java/android/net/metrics/ConnectivityServiceChangeEvent.java
index c6fcb2d..731d5e6 100644
--- a/core/java/android/net/metrics/ConnectivityServiceChangeEvent.java
+++ b/core/java/android/net/metrics/ConnectivityServiceChangeEvent.java
@@ -25,18 +25,30 @@
public class ConnectivityServiceChangeEvent extends IpConnectivityEvent implements Parcelable {
public static final String TAG = "ConnectivityServiceChangeEvent";
- private int mNetId;
+ // The ID of the network that has become the new default or NETID_UNSET if none.
+ private final int mNetId;
+ // The ID of the network that was the default before or NETID_UNSET if none.
+ private final int mPrevNetId;
+ // The list of transport types of the new default network, for example TRANSPORT_WIFI, as
+ // defined in NetworkCapabilities.java.
+ private final int[] mTransportTypes;
- public ConnectivityServiceChangeEvent(int netId) {
+ public ConnectivityServiceChangeEvent(int netId, int prevNetId, int[] transportTypes) {
mNetId = netId;
+ mPrevNetId = prevNetId;
+ mTransportTypes = transportTypes;
}
public ConnectivityServiceChangeEvent(Parcel in) {
mNetId = in.readInt();
+ mPrevNetId = in.readInt();
+ mTransportTypes = in.createIntArray();
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mNetId);
+ out.writeInt(mPrevNetId);
+ out.writeIntArray(mTransportTypes);
}
public static final Parcelable.Creator<ConnectivityServiceChangeEvent> CREATOR
@@ -50,8 +62,8 @@
}
};
- public static void logEvent(int netId) {
+ public static void logEvent(int netId, int prevNetId, int[] transportTypes) {
IpConnectivityEvent.logEvent(IpConnectivityEvent.IPCE_CONSRV_DEFAULT_NET_CHANGE,
- new ConnectivityServiceChangeEvent(netId));
+ new ConnectivityServiceChangeEvent(netId, prevNetId, transportTypes));
}
};
diff --git a/core/java/android/net/metrics/IpConnectivityEvent.java b/core/java/android/net/metrics/IpConnectivityEvent.java
index ec42890..59c1cfe 100644
--- a/core/java/android/net/metrics/IpConnectivityEvent.java
+++ b/core/java/android/net/metrics/IpConnectivityEvent.java
@@ -28,14 +28,17 @@
// DHCP = DhcpClient
// NETMON = NetworkMonitorEvent
// CONSRV = ConnectivityServiceEvent
+ // IPMGR = IpManager
public static final String TAG = "IpConnectivityEvent";
public static final int IPCE_IPRM_BASE = 0*1024;
public static final int IPCE_DHCP_BASE = 1*1024;
public static final int IPCE_NETMON_BASE = 2*1024;
public static final int IPCE_CONSRV_BASE = 3*1024;
+ public static final int IPCE_IPMGR_BASE = 4*1024;
public static final int IPCE_IPRM_PROBE_RESULT = IPCE_IPRM_BASE + 0;
public static final int IPCE_IPRM_MESSAGE_RECEIVED = IPCE_IPRM_BASE + 1;
+ public static final int IPCE_IPRM_REACHABILITY_LOST = IPCE_IPRM_BASE + 2;
public static final int IPCE_DHCP_RECV_ERROR = IPCE_DHCP_BASE + 0;
public static final int IPCE_DHCP_PARSE_ERROR = IPCE_DHCP_BASE + 1;
public static final int IPCE_DHCP_TIMEOUT = IPCE_DHCP_BASE + 2;
@@ -43,6 +46,9 @@
public static final int IPCE_NETMON_STATE_CHANGE = IPCE_NETMON_BASE + 0;
public static final int IPCE_NETMON_CHECK_RESULT = IPCE_NETMON_BASE + 1;
public static final int IPCE_CONSRV_DEFAULT_NET_CHANGE = IPCE_CONSRV_BASE + 0;
+ public static final int IPCE_IPMGR_PROVISIONING_OK = IPCE_IPMGR_BASE + 0;
+ public static final int IPCE_IPMGR_PROVISIONING_FAIL = IPCE_IPMGR_BASE + 1;
+ public static final int IPCE_IPMGR_COMPLETE_LIFECYCLE = IPCE_IPMGR_BASE + 2;
private static ConnectivityMetricsLogger mMetricsLogger = new ConnectivityMetricsLogger();
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
new file mode 100644
index 0000000..6328ccb
--- /dev/null
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * {@hide}
+ */
+public class IpManagerEvent extends IpConnectivityEvent implements Parcelable {
+ private String mIfName;
+ private long mDurationMs;
+
+ public IpManagerEvent(String ifName, long duration) {
+ mIfName = ifName;
+ mDurationMs = duration;
+ }
+
+ public IpManagerEvent(Parcel in) {
+ mIfName = in.readString();
+ mDurationMs = in.readLong();
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mIfName);
+ out.writeLong(mDurationMs);
+ }
+
+ public static final Parcelable.Creator<IpManagerEvent> CREATOR
+ = new Parcelable.Creator<IpManagerEvent>() {
+ public IpManagerEvent createFromParcel(Parcel in) {
+ return new IpManagerEvent(in);
+ }
+
+ public IpManagerEvent[] newArray(int size) {
+ return new IpManagerEvent[size];
+ }
+ };
+
+ public static void logEvent(int eventType, String ifName, long durationMs) {
+ IpConnectivityEvent.logEvent(eventType, new IpManagerEvent(ifName, durationMs));
+ }
+};
diff --git a/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java b/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java
new file mode 100644
index 0000000..0f14210
--- /dev/null
+++ b/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * {@hide}
+ */
+public class IpReachabilityMonitorLostEvent extends IpConnectivityEvent
+ implements Parcelable {
+ private String mIfName;
+
+ public IpReachabilityMonitorLostEvent(String ifName) {
+ mIfName = ifName;
+ }
+
+ public IpReachabilityMonitorLostEvent(Parcel in) {
+ mIfName = in.readString();
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mIfName);
+ }
+
+ public static final Parcelable.Creator<IpReachabilityMonitorLostEvent> CREATOR
+ = new Parcelable.Creator<IpReachabilityMonitorLostEvent>() {
+ public IpReachabilityMonitorLostEvent createFromParcel(Parcel in) {
+ return new IpReachabilityMonitorLostEvent(in);
+ }
+
+ public IpReachabilityMonitorLostEvent[] newArray(int size) {
+ return new IpReachabilityMonitorLostEvent[size];
+ }
+ };
+
+ public static void logEvent(String ifName) {
+ IpConnectivityEvent.logEvent(IpConnectivityEvent.IPCE_IPRM_REACHABILITY_LOST,
+ new IpReachabilityMonitorLostEvent(ifName));
+ }
+};
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e3de810..a3a40eb 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1774,7 +1774,6 @@
title = "";
mTitle = TextUtils.stringOrSpannedString(title);
- accessibilityTitle = mTitle;
}
public final CharSequence getTitle() {
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index c4347f8..8b9d503 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -17,9 +17,15 @@
package com.android.internal.widget;
+import com.android.internal.R;
+
import android.content.Context;
import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -38,7 +44,6 @@
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.OverScroller;
-import com.android.internal.R;
public class ResolverDrawerLayout extends ViewGroup {
private static final String TAG = "ResolverDrawerLayout";
@@ -86,6 +91,8 @@
private final OverScroller mScroller;
private final VelocityTracker mVelocityTracker;
+ private Drawable mScrollIndicatorDrawable;
+
private OnDismissedListener mOnDismissedListener;
private RunOnDismissedListener mRunOnDismissedListener;
@@ -127,6 +134,8 @@
mMaxCollapsedHeight);
a.recycle();
+ mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
+
mScroller = new OverScroller(context, AnimationUtils.loadInterpolator(context,
android.R.interpolator.decelerate_quint));
mVelocityTracker = VelocityTracker.obtain();
@@ -202,8 +211,7 @@
}
final boolean isCollapsedNew = mCollapseOffset != 0;
if (isCollapsedOld != isCollapsedNew) {
- notifyViewAccessibilityStateChangedIfNeeded(
- AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+ onCollapsedChanged(isCollapsedNew);
}
} else {
// Start out collapsed at first unless we restored state for otherwise
@@ -442,8 +450,7 @@
mTopOffset += dy;
final boolean isCollapsedNew = newPos != 0;
if (isCollapsedOld != isCollapsedNew) {
- notifyViewAccessibilityStateChangedIfNeeded(
- AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+ onCollapsedChanged(isCollapsedNew);
}
postInvalidateOnAnimation();
return dy;
@@ -451,6 +458,15 @@
return 0;
}
+ private void onCollapsedChanged(boolean isCollapsed) {
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+
+ if (mScrollIndicatorDrawable != null) {
+ setWillNotDraw(!isCollapsed);
+ }
+ }
+
void dispatchOnDismissed() {
if (mOnDismissedListener != null) {
mOnDismissedListener.onDismissed();
@@ -709,6 +725,15 @@
}
@Override
+ public void onDrawForeground(Canvas canvas) {
+ if (mScrollIndicatorDrawable != null) {
+ mScrollIndicatorDrawable.draw(canvas);
+ }
+
+ super.onDrawForeground(canvas);
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int sourceWidth = MeasureSpec.getSize(widthMeasureSpec);
int widthSize = sourceWidth;
@@ -794,6 +819,8 @@
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int width = getWidth();
+ View indicatorHost = null;
+
int ypos = mTopOffset;
int leftEdge = getPaddingLeft();
int rightEdge = width - getPaddingRight();
@@ -802,6 +829,9 @@
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (lp.hasNestedScrollIndicator) {
+ indicatorHost = child;
+ }
if (child.getVisibility() == GONE) {
continue;
@@ -822,6 +852,20 @@
ypos = bottom + lp.bottomMargin;
}
+
+ if (mScrollIndicatorDrawable != null) {
+ if (indicatorHost != null) {
+ final int left = indicatorHost.getLeft();
+ final int right = indicatorHost.getRight();
+ final int bottom = indicatorHost.getTop();
+ final int top = bottom - mScrollIndicatorDrawable.getIntrinsicHeight();
+ mScrollIndicatorDrawable.setBounds(left, top, right, bottom);
+ setWillNotDraw(!isCollapsed());
+ } else {
+ mScrollIndicatorDrawable = null;
+ setWillNotDraw(true);
+ }
+ }
}
@Override
@@ -861,6 +905,7 @@
public static class LayoutParams extends MarginLayoutParams {
public boolean alwaysShow;
public boolean ignoreOffset;
+ public boolean hasNestedScrollIndicator;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
@@ -873,6 +918,9 @@
ignoreOffset = a.getBoolean(
R.styleable.ResolverDrawerLayout_LayoutParams_layout_ignoreOffset,
false);
+ hasNestedScrollIndicator = a.getBoolean(
+ R.styleable.ResolverDrawerLayout_LayoutParams_layout_hasNestedScrollIndicator,
+ false);
a.recycle();
}
@@ -884,6 +932,7 @@
super(source);
this.alwaysShow = source.alwaysShow;
this.ignoreOffset = source.ignoreOffset;
+ this.hasNestedScrollIndicator = source.hasNestedScrollIndicator;
}
public LayoutParams(MarginLayoutParams source) {
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index 5850e50..ae94503 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -30,33 +30,37 @@
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
android:elevation="8dp"
- android:background="@color/white" >
- <TextView android:id="@+id/profile_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:layout_marginEnd="8dp"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:visibility="gone"
- style="?attr/borderlessButtonStyle"
- android:textAppearance="?attr/textAppearanceButton"
- android:textColor="@color/material_deep_teal_500"
- android:gravity="center_vertical"
- android:layout_alignParentTop="true"
- android:layout_alignParentRight="true"
- android:singleLine="true"/>
- <TextView android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:minHeight="56dp"
- android:textAppearance="?attr/textAppearanceMedium"
- android:gravity="start|center_vertical"
- android:paddingStart="?attr/dialogPreferredPadding"
- android:paddingEnd="?attr/dialogPreferredPadding"
- android:paddingTop="8dp"
- android:layout_below="@id/profile_button"
- android:layout_alignParentLeft="true"
- android:paddingBottom="8dp" />
+ android:background="@color/white">
+
+ <TextView
+ android:id="@+id/profile_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:layout_marginEnd="8dp"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:visibility="gone"
+ style="?attr/borderlessButtonStyle"
+ android:textAppearance="?attr/textAppearanceButton"
+ android:textColor="@color/material_deep_teal_500"
+ android:gravity="center_vertical"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:singleLine="true" />
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="56dp"
+ android:textAppearance="?attr/textAppearanceMedium"
+ android:gravity="start|center_vertical"
+ android:paddingStart="?attr/dialogPreferredPadding"
+ android:paddingEnd="?attr/dialogPreferredPadding"
+ android:paddingTop="8dp"
+ android:layout_below="@id/profile_button"
+ android:layout_alignParentLeft="true"
+ android:paddingBottom="8dp" />
</RelativeLayout>
<ListView
@@ -68,6 +72,7 @@
android:background="@color/white"
android:elevation="8dp"
android:nestedScrollingEnabled="true"
+ android:scrollIndicators="top|bottom"
android:divider="@null" />
<TextView android:id="@+id/empty"
@@ -84,11 +89,12 @@
<LinearLayout
android:id="@+id/button_bar"
android:visibility="gone"
- style="?android:attr/buttonBarStyle"
+ style="?attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_ignoreOffset="true"
android:layout_alwaysShow="true"
+ android:layout_hasNestedScrollIndicator="true"
android:gravity="end|center_vertical"
android:orientation="horizontal"
android:layoutDirection="locale"
@@ -99,26 +105,30 @@
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:elevation="8dp">
- <Button android:id="@+id/button_once"
- android:layout_width="wrap_content"
- android:layout_gravity="start"
- android:maxLines="2"
- style="?android:attr/buttonBarNegativeButtonStyle"
- android:minHeight="@dimen/alert_dialog_button_bar_height"
- android:layout_height="wrap_content"
- android:enabled="false"
- android:text="@string/activity_resolver_use_once"
- android:onClick="onButtonClick" />
- <Button android:id="@+id/button_always"
- android:layout_width="wrap_content"
- android:layout_gravity="end"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height"
- style="?android:attr/buttonBarPositiveButtonStyle"
- android:layout_height="wrap_content"
- android:enabled="false"
- android:text="@string/activity_resolver_use_always"
- android:onClick="onButtonClick" />
+
+ <Button
+ android:id="@+id/button_once"
+ android:layout_width="wrap_content"
+ android:layout_gravity="start"
+ android:maxLines="2"
+ style="?attr/buttonBarNegativeButtonStyle"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:text="@string/activity_resolver_use_once"
+ android:onClick="onButtonClick" />
+
+ <Button
+ android:id="@+id/button_always"
+ android:layout_width="wrap_content"
+ android:layout_gravity="end"
+ android:maxLines="2"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ style="?attr/buttonBarPositiveButtonStyle"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:text="@string/activity_resolver_use_always"
+ android:onClick="onButtonClick" />
</LinearLayout>
</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index 31361e5..02dc2ed 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -22,8 +22,7 @@
android:layout_height="match_parent"
android:maxWidth="@dimen/resolver_max_width"
android:maxCollapsedHeight="144dp"
- android:id="@id/contentPanel"
- >
+ android:id="@id/contentPanel">
<LinearLayout
android:layout_width="match_parent"
@@ -31,66 +30,75 @@
android:layout_alwaysShow="true"
android:orientation="vertical"
android:background="@color/white"
- android:elevation="8dp" >
+ android:elevation="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="64dp"
- android:orientation="horizontal" >
+ android:orientation="horizontal">
- <ImageView android:id="@+id/icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_gravity="start|top"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
- android:layout_marginTop="20dp"
- android:scaleType="fitCenter" />
- <TextView android:id="@+id/title"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:layout_marginStart="16dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:gravity="start|center_vertical"
- android:paddingEnd="16dp" />
- <LinearLayout android:id="@+id/profile_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:layout_marginTop="4dp"
- android:layout_marginEnd="4dp"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:paddingTop="4dp"
- android:paddingBottom="4dp"
- android:focusable="true"
- android:visibility="gone"
- style="?attr/borderlessButtonStyle">
- <ImageView android:id="@+id/icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_gravity="start|center_vertical"
- android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
- android:layout_marginTop="12dp"
- android:layout_marginBottom="12dp"
- android:scaleType="fitCenter" />
- <TextView android:id="@id/text1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start|center_vertical"
- android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
- android:textAppearance="?attr/textAppearanceButton"
- android:textColor="?attr/textColorPrimary"
- android:minLines="1"
- android:maxLines="1"
- android:ellipsize="marquee" />
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="start|top"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginTop="20dp"
+ android:scaleType="fitCenter" />
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="?attr/listPreferredItemHeight"
+ android:layout_marginStart="16dp"
+ android:textAppearance="?attr/textAppearanceMedium"
+ android:gravity="start|center_vertical"
+ android:paddingEnd="16dp" />
+
+ <LinearLayout
+ android:id="@+id/profile_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:layout_marginTop="4dp"
+ android:layout_marginEnd="4dp"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp"
+ android:focusable="true"
+ android:visibility="gone"
+ style="?attr/borderlessButtonStyle">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="start|center_vertical"
+ android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="12dp"
+ android:scaleType="fitCenter" />
+
+ <TextView
+ android:id="@id/text1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start|center_vertical"
+ android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
+ android:textAppearance="?attr/textAppearanceButton"
+ android:textColor="?attr/textColorPrimary"
+ android:minLines="1"
+ android:maxLines="1"
+ android:ellipsize="marquee" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/button_bar"
android:visibility="gone"
- style="?android:attr/buttonBarStyle"
+ style="?attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
@@ -104,30 +112,36 @@
android:paddingEnd="12dp"
android:background="@color/white"
android:elevation="8dp">
- <Button android:id="@+id/button_once"
- android:layout_width="wrap_content"
- android:layout_gravity="start"
- android:maxLines="2"
- style="?android:attr/buttonBarNegativeButtonStyle"
- android:minHeight="@dimen/alert_dialog_button_bar_height"
- android:layout_height="wrap_content"
- android:enabled="false"
- android:text="@string/activity_resolver_use_once"
- android:onClick="onButtonClick" />
- <Button android:id="@+id/button_always"
- android:layout_width="wrap_content"
- android:layout_gravity="end"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height"
- style="?android:attr/buttonBarPositiveButtonStyle"
- android:layout_height="wrap_content"
- android:enabled="false"
- android:text="@string/activity_resolver_use_always"
- android:onClick="onButtonClick" />
+
+ <Button
+ android:id="@+id/button_once"
+ android:layout_width="wrap_content"
+ android:layout_gravity="start"
+ android:maxLines="2"
+ style="?attr/buttonBarNegativeButtonStyle"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:text="@string/activity_resolver_use_once"
+ android:onClick="onButtonClick" />
+
+ <Button
+ android:id="@+id/button_always"
+ android:layout_width="wrap_content"
+ android:layout_gravity="end"
+ android:maxLines="2"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ style="?attr/buttonBarPositiveButtonStyle"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:text="@string/activity_resolver_use_always"
+ android:onClick="onButtonClick" />
</LinearLayout>
- <View android:layout_width="match_parent"
- android:layout_height="1dp"
- android:background="?android:attr/dividerVertical" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="?attr/dividerVertical" />
</LinearLayout>
<ListView
@@ -139,7 +153,6 @@
android:background="@color/white"
android:elevation="8dp"
android:nestedScrollingEnabled="true"
- android:divider="@null"
- />
+ android:divider="@null" />
</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a320ef6..85e0b88 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8138,6 +8138,7 @@
<attr name="layout_alwaysShow" format="boolean" />
<attr name="layout_ignoreOffset" format="boolean" />
<attr name="layout_gravity" />
+ <attr name="layout_hasNestedScrollIndicator" format="boolean" />
</declare-styleable>
<!-- @hide -->
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index fba25ab..22454ad 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -524,6 +524,7 @@
}
if (mActionMode != null) {
+ assert(!mSelected.isEmpty());
final String title = Shared.getQuantityString(getActivity(),
R.plurals.elements_selected, mSelected.size());
mActionMode.setTitle(title);
@@ -809,6 +810,8 @@
// the user cancels the delete.
if (mActionMode != null) {
mActionMode.finish();
+ } else {
+ Log.w(TAG, "Action mode is null before deleting documents.");
}
// Hide the files in the UI...since the operation
// might be queued up on FileOperationService.
@@ -1436,7 +1439,8 @@
// This has to be handled here instead of in a keyboard shortcut, because
// keyboard shortcuts all have to be modified with the 'Ctrl' key.
if (mSelectionManager.hasSelection()) {
- deleteDocuments(mSelectionManager.getSelection());
+ Selection selection = mSelectionManager.getSelection(new Selection());
+ deleteDocuments(selection);
}
// Always handle the key, even if there was nothing to delete. This is a
// precaution to prevent other handlers from potentially picking up the event
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_text_focus_gain_animation.xml
similarity index 92%
rename from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
rename to packages/SystemUI/res/anim/tv_pip_controls_text_focus_gain_animation.xml
index 681ff91..257bf35 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_controls_text_focus_gain_animation.xml
@@ -18,4 +18,4 @@
android:propertyName="alpha"
android:valueTo="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ android:duration="100" />
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_text_focus_lose_animation.xml
similarity index 92%
rename from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
rename to packages/SystemUI/res/anim/tv_pip_controls_text_focus_lose_animation.xml
index e6deb0f..e032008 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_controls_text_focus_lose_animation.xml
@@ -18,4 +18,4 @@
android:propertyName="alpha"
android:valueTo="0"
android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ android:duration="100" />
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml b/packages/SystemUI/res/anim/tv_pip_menu_fade_in_animation.xml
similarity index 92%
copy from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
copy to packages/SystemUI/res/anim/tv_pip_menu_fade_in_animation.xml
index 681ff91..257bf35 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_menu_fade_in_animation.xml
@@ -18,4 +18,4 @@
android:propertyName="alpha"
android:valueTo="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ android:duration="100" />
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml b/packages/SystemUI/res/anim/tv_pip_menu_fade_out_animation.xml
similarity index 92%
copy from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
copy to packages/SystemUI/res/anim/tv_pip_menu_fade_out_animation.xml
index e6deb0f..e032008 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_menu_fade_out_animation.xml
@@ -18,4 +18,4 @@
android:propertyName="alpha"
android:valueTo="0"
android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ android:duration="100" />
diff --git a/packages/SystemUI/res/drawable/tv_pip_button_focused.xml b/packages/SystemUI/res/drawable/tv_pip_button_focused.xml
index 405ea0c..0db1a57 100644
--- a/packages/SystemUI/res/drawable/tv_pip_button_focused.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_button_focused.xml
@@ -14,11 +14,5 @@
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size
- android:width="34dp"
- android:height="34dp" />
- <solid
- android:color="#4DFFFFFF" />
-</shape>
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="#9AFFFFFF" android:radius="17dp" />
diff --git a/packages/SystemUI/res/drawable/tv_pip_close_button.xml b/packages/SystemUI/res/drawable/tv_pip_close_button.xml
deleted file mode 100644
index 186a4ba..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_close_button.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:constantSize="true">
- <item android:state_focused="true">
- <layer-list>
- <item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_close_white"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
- <item>
- <layer-list>
- <item android:drawable="@drawable/ic_close_white"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
-</selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_full_button.xml b/packages/SystemUI/res/drawable/tv_pip_full_button.xml
deleted file mode 100644
index c48dc828..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_full_button.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:constantSize="true">
- <item android:state_focused="true">
- <layer-list>
- <item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_fullscreen_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
- <item>
- <layer-list>
- <item android:drawable="@drawable/ic_fullscreen_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
-</selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml b/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
index e247dec..2b58fc5 100644
--- a/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
@@ -16,8 +16,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <gradient
- android:startColor="#B2000000"
- android:endColor="#00000000"
- android:angle="90"/>
+ <stroke android:width="1dp" android:color="#33FFFFFF" />
</shape>
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml b/packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml
similarity index 61%
copy from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
copy to packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml
index 681ff91..e247dec 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!--
+ Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:propertyName="alpha"
- android:valueTo="1"
- android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ <gradient
+ android:startColor="#B2000000"
+ android:endColor="#00000000"
+ android:angle="90"/>
+</shape>
diff --git a/packages/SystemUI/res/drawable/tv_pip_pause_button.xml b/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
deleted file mode 100644
index bcc8973..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:constantSize="true">
- <item android:state_focused="true">
- <layer-list>
- <item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_pause_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
- <item>
- <layer-list>
- <item android:drawable="@drawable/ic_pause_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
-</selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_play_button.xml b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
deleted file mode 100644
index f77ea1d..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_play_button.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:constantSize="true">
- <item android:state_focused="true">
- <layer-list>
- <item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_play_arrow_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
- <item>
- <layer-list>
- <item android:drawable="@drawable/ic_play_arrow_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
-</selector>
diff --git a/packages/SystemUI/res/layout/tv_pip_control_button.xml b/packages/SystemUI/res/layout/tv_pip_control_button.xml
new file mode 100644
index 0000000..0beeda1
--- /dev/null
+++ b/packages/SystemUI/res/layout/tv_pip_control_button.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- Layout for {@link com.android.systemui.tv.pip.PipControlButtonView}. -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <ImageView android:id="@+id/button"
+ android:layout_width="34dp"
+ android:layout_height="34dp"
+ android:padding="5dp"
+ android:focusable="true"
+ android:src="@drawable/ic_fullscreen_white_24dp"
+ android:background="@drawable/tv_pip_button_focused"
+ android:layerType="software" />
+
+ <TextView android:id="@+id/desc"
+ android:layout_width="100dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="3dp"
+ android:gravity="center"
+ android:text="@string/pip_fullscreen"
+ android:alpha="0"
+ android:fontFamily="sans-serif"
+ android:textSize="12sp"
+ android:textColor="#EEEEEE" />
+</merge>
diff --git a/packages/SystemUI/res/layout/tv_pip_controls.xml b/packages/SystemUI/res/layout/tv_pip_controls.xml
index 563441f..0a2f320 100644
--- a/packages/SystemUI/res/layout/tv_pip_controls.xml
+++ b/packages/SystemUI/res/layout/tv_pip_controls.xml
@@ -20,77 +20,26 @@
<!-- Layout for {@link com.android.systemui.tv.pip.PipControlsView}. -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <LinearLayout
+ <com.android.systemui.tv.pip.PipControlButtonView
+ android:id="@+id/full_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:gravity="center">
+ android:src="@drawable/ic_fullscreen_white_24dp"
+ android:text="@string/pip_fullscreen" />
- <ImageView android:id="@+id/full_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:src="@drawable/tv_pip_full_button" />
-
- <TextView android:id="@+id/full_desc"
- android:layout_width="100dp"
- android:layout_height="wrap_content"
- android:layout_marginTop="3dp"
- android:gravity="center"
- android:visibility="invisible"
- android:text="@string/pip_fullscreen"
- android:fontFamily="sans-serif"
- android:textSize="12sp"
- android:textColor="#EEEEEE" />
- </LinearLayout>
-
- <LinearLayout
+ <com.android.systemui.tv.pip.PipControlButtonView
+ android:id="@+id/close_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginStart="-50dp"
- android:orientation="vertical"
- android:gravity="center">
+ android:src="@drawable/ic_close_white"
+ android:text="@string/pip_close" />
- <ImageView android:id="@+id/close_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:src="@drawable/tv_pip_close_button" />
-
- <TextView android:id="@+id/close_desc"
- android:layout_width="100dp"
- android:layout_height="wrap_content"
- android:layout_marginTop="3dp"
- android:gravity="center"
- android:visibility="invisible"
- android:text="@string/pip_close"
- android:fontFamily="sans-serif"
- android:textSize="12sp"
- android:textColor="#EEEEEE" />
- </LinearLayout>
-
- <LinearLayout android:id="@+id/play_pause"
+ <com.android.systemui.tv.pip.PipControlButtonView
+ android:id="@+id/play_pause_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginStart="-50dp"
- android:orientation="vertical"
- android:gravity="center" >
-
- <ImageView android:id="@+id/play_pause_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:src="@drawable/tv_pip_pause_button" />
-
- <TextView android:id="@+id/play_pause_desc"
- android:layout_width="100dp"
- android:layout_height="wrap_content"
- android:layout_marginTop="3dp"
- android:gravity="center"
- android:visibility="invisible"
- android:text="@string/pip_pause"
- android:fontFamily="sans-serif"
- android:textSize="12sp"
- android:textColor="#EEEEEE" />
- </LinearLayout>
+ android:src="@drawable/ic_pause_white_24dp"
+ android:text="@string/pip_pause" />
</merge>
diff --git a/packages/SystemUI/res/layout/tv_pip_menu.xml b/packages/SystemUI/res/layout/tv_pip_menu.xml
index 2647a99..72a4929 100644
--- a/packages/SystemUI/res/layout/tv_pip_menu.xml
+++ b/packages/SystemUI/res/layout/tv_pip_menu.xml
@@ -29,5 +29,6 @@
<com.android.systemui.tv.pip.PipControlsView
android:id="@+id/pip_controls"
android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:alpha="0" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/tv_pip_overlay.xml b/packages/SystemUI/res/layout/tv_pip_overlay.xml
index 64bf3b5..608680c 100644
--- a/packages/SystemUI/res/layout/tv_pip_overlay.xml
+++ b/packages/SystemUI/res/layout/tv_pip_overlay.xml
@@ -19,7 +19,8 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:background="@drawable/tv_pip_overlay_background">
<TextView
android:id="@+id/guide_overlay"
@@ -33,7 +34,7 @@
android:textSize="14sp"
android:textColor="#EEEEEE"
android:fontFamily="sans-serif"
- android:background="@drawable/tv_pip_overlay_background"
+ android:background="@drawable/tv_pip_overlay_text_background"
android:lineSpacingMultiplier="1.465"
android:gravity="center"
android:maxLines="2"
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index f536f86..e938d09 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -54,8 +54,6 @@
<!-- Extra space around the PIP and its outline in PIP onboarding activity -->
<dimen name="tv_pip_bounds_space">3dp</dimen>
- <!-- Extra space around the PIP control button icon to match with the focused circle -->
- <dimen name="tv_pip_button_icon_padding">5dp</dimen>
<!-- Values for entering Recents and exiting Recents -->
<dimen name="recents_tv_home_recents_shift">125dip</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 6b476ee..df79669 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -66,6 +66,7 @@
import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
+import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
@@ -752,6 +753,13 @@
mIgnoreAltTabRelease = true;
}
+ public final void onBusEvent(final DragEndEvent event) {
+ // Handle the case where we drop onto a dock region
+ if (event.dropTarget instanceof TaskStack.DockState) {
+ mScrimViews.animateScrimToCurrentNavBarState(false /* hasStackTasks */);
+ }
+ }
+
@Override
public boolean onPreDraw() {
mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index fda340d..6d32293 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -175,7 +175,11 @@
ssp.registerTaskStackListener(mTaskStackListener);
// Initialize the static configuration resources
- reloadHeaderBarLayout();
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ mDummyStackView = new TaskStackView(mContext);
+ mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
+ null, false);
+ reloadResources();
// When we start, preload the data associated with the previous recent tasks.
// We can use a new plan since the caches will be the same.
@@ -194,7 +198,9 @@
}
public void onConfigurationChanged() {
- reloadHeaderBarLayout();
+ reloadResources();
+ mDummyStackView.reloadOnConfigurationChange();
+ mHeaderBar.onConfigurationChanged();
}
/**
@@ -542,11 +548,10 @@
}
/**
- * Reloads all the layouts for the header bar transition.
+ * Reloads all the resources for the current configuration.
*/
- private void reloadHeaderBarLayout() {
+ private void reloadResources() {
Resources res = mContext.getResources();
- LayoutInflater inflater = LayoutInflater.from(mContext);
mStatusBarHeight = res.getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
@@ -561,9 +566,6 @@
R.dimen.recents_task_view_header_height_tablet_land,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height_tablet_land);
- mDummyStackView = new TaskStackView(mContext);
- mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
- null, false);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 9f9c48f..68c46a9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -315,6 +315,15 @@
return key.id != affiliationTaskId;
}
+ /**
+ * Returns the top activity component.
+ */
+ public ComponentName getTopComponent() {
+ return topActivity != null
+ ? topActivity
+ : key.baseIntent.getComponent();
+ }
+
@Override
public boolean equals(Object o) {
// Check that the id matches
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 59b7560..86d68c2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -541,7 +541,7 @@
true /* scaleUp */);
MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP,
- event.task.topActivity.flattenToShortString());
+ event.task.getTopComponent().flattenToShortString());
} else {
// Animate the overlay alpha back to 0
updateVisibleDockRegions(null, true /* isDefaultDockState */, -1,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 5fbc037..70c4dbd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -162,7 +162,8 @@
mVisibleDockStates.clear();
if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()
&& mDividerSnapAlgorithm.isSplitScreenFeasible()) {
- Recents.logDockAttempt(mRv.getContext(), event.task.topActivity, event.task.resizeMode);
+ Recents.logDockAttempt(mRv.getContext(), event.task.getTopComponent(),
+ event.task.resizeMode);
if (!event.task.isDockable) {
EventBus.getDefault().send(new ShowIncompatibleAppOverlayEvent());
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 07a1d4e..dce2353 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -152,7 +152,7 @@
/**
* Animates the scrim to match the state of the current nav bar.
*/
- private void animateScrimToCurrentNavBarState(boolean hasStackTasks) {
+ public void animateScrimToCurrentNavBarState(boolean hasStackTasks) {
boolean hasNavBarScrim = isNavBarScrimRequired(hasStackTasks);
if (mHasNavBarScrim != hasNavBarScrim) {
AnimationProps animation = hasNavBarScrim
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 0fc45ed..63018c5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -353,8 +353,8 @@
public void updateToInitialState(boolean scrollToInitialState) {
if (scrollToInitialState) {
mStackScroller.setStackScrollToInitialState();
+ mLayoutAlgorithm.updateToInitialState(mStack.getStackTasks());
}
- mLayoutAlgorithm.updateToInitialState(mStack.getStackTasks());
}
/** Updates the list of task views */
@@ -1221,7 +1221,9 @@
// TaskViews with the stack so that we can lay them out
if (mAwaitingFirstLayout || mInitialState != INITIAL_STATE_UPDATE_NONE) {
updateToInitialState(mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY);
- mInitialState = INITIAL_STATE_UPDATE_NONE;
+ if (!mAwaitingFirstLayout) {
+ mInitialState = INITIAL_STATE_UPDATE_NONE;
+ }
}
// Rebind all the views, including the ignore ones
@@ -1281,6 +1283,7 @@
if (mAwaitingFirstLayout || !mEnterAnimationComplete) {
mAwaitingFirstLayout = false;
+ mInitialState = INITIAL_STATE_UPDATE_NONE;
onFirstLayout();
}
}
@@ -1836,9 +1839,17 @@
// Calculate the new task stack bounds that matches the window size that Recents will
// have after the drop
final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
+ Rect systemInsets = new Rect(mStableLayoutAlgorithm.mSystemInsets);
+ // When docked, the nav bar insets are consumed and the activity is measured without
+ // insets. However, the window bounds include the insets, so we need to subtract them
+ // here to make them identical.
+ int height = getMeasuredHeight();
+ height -= systemInsets.bottom;
+ systemInsets.bottom = 0;
mStackBounds.set(dockState.getDockedTaskStackBounds(getMeasuredWidth(),
- getMeasuredHeight(), mDividerSize, mLayoutAlgorithm.mSystemInsets,
+ height, mDividerSize, mLayoutAlgorithm.mSystemInsets,
mLayoutAlgorithm, getResources(), mWindowRect));
+ mLayoutAlgorithm.setSystemInsets(systemInsets);
mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
updateLayoutAlgorithm(true /* boundScroll */);
@@ -1849,6 +1860,7 @@
mWindowRect.set(mStableWindowRect);
mStackBounds.set(mStableStackBounds);
removeIgnoreTask(event.task);
+ mLayoutAlgorithm.setSystemInsets(mStableLayoutAlgorithm.mSystemInsets);
mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
updateLayoutAlgorithm(true /* boundScroll */);
@@ -1987,8 +1999,7 @@
}
public final void onBusEvent(ConfigurationChangedEvent event) {
- mStableLayoutAlgorithm.reloadOnConfigurationChange(getContext());
- mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
+ reloadOnConfigurationChange();
// Notify the task views of the configuration change so they can reload their resources
if (!event.fromMultiWindow) {
@@ -2002,12 +2013,15 @@
}
// Trigger a new layout and update to the initial state if necessary
- if (event.fromMultiWindow) {
- mInitialState = INITIAL_STATE_UPDATE_ALL;
- } else if (event.fromOrientationChange) {
+ if (event.fromMultiWindow || event.fromOrientationChange) {
mInitialState = INITIAL_STATE_UPDATE_LAYOUT_ONLY;
+ requestLayout();
}
- requestLayout();
+ }
+
+ public void reloadOnConfigurationChange() {
+ mStableLayoutAlgorithm.reloadOnConfigurationChange(getContext());
+ mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 16d8e53..f98d3d5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -280,27 +280,31 @@
/**
* Update the header view when the configuration changes.
*/
- void onConfigurationChanged() {
+ public void onConfigurationChanged() {
// Update the dimensions of everything in the header. We do this because we need to use
// resources for the display, and not the current configuration.
Resources res = getResources();
- mHeaderBarHeight = TaskStackLayoutAlgorithm.getDimensionForDevice(res,
+ int headerBarHeight = TaskStackLayoutAlgorithm.getDimensionForDevice(res,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height_tablet_land,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height_tablet_land);
- mHeaderButtonPadding = TaskStackLayoutAlgorithm.getDimensionForDevice(res,
+ int headerButtonPadding = TaskStackLayoutAlgorithm.getDimensionForDevice(res,
R.dimen.recents_task_view_header_button_padding,
R.dimen.recents_task_view_header_button_padding,
R.dimen.recents_task_view_header_button_padding,
R.dimen.recents_task_view_header_button_padding_tablet_land,
R.dimen.recents_task_view_header_button_padding,
R.dimen.recents_task_view_header_button_padding_tablet_land);
- updateLayoutParams(mIconView, mTitleView, mMoveTaskButton, mDismissButton);
- if (mAppOverlayView != null) {
- updateLayoutParams(mAppIconView, mAppTitleView, null, mAppInfoView);
+ if (headerBarHeight != mHeaderBarHeight || headerButtonPadding != mHeaderButtonPadding) {
+ mHeaderBarHeight = headerBarHeight;
+ mHeaderButtonPadding = headerButtonPadding;
+ updateLayoutParams(mIconView, mTitleView, mMoveTaskButton, mDismissButton);
+ if (mAppOverlayView != null) {
+ updateLayoutParams(mAppIconView, mAppTitleView, null, mAppInfoView);
+ }
}
}
@@ -434,7 +438,6 @@
/** Binds the bar view to the task */
public void rebindToTask(Task t, boolean touchExplorationEnabled, boolean disabledInSafeMode) {
- SystemServicesProxy ssp = Recents.getSystemServices();
mTask = t;
// If an activity icon is defined, then we use that as the primary icon to show in the bar,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index ebefdde..52fb470 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -674,6 +674,13 @@
} else if (!selfFullscreen && otherFullscreen) {
return 1;
}
+
+ if (remoteInputActive && !o.remoteInputActive) {
+ return -1;
+ } else if (!remoteInputActive && o.remoteInputActive) {
+ return 1;
+ }
+
return postTime < o.postTime ? 1
: postTime == o.postTime ? entry.key.compareTo(o.entry.key)
: -1;
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
new file mode 100644
index 0000000..c65415e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.tv.pip;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View.OnFocusChangeListener;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+/**
+ * A view containing PIP controls including fullscreen, close, and media controls.
+ */
+public class PipControlButtonView extends LinearLayout {
+ private OnFocusChangeListener mFocusChangeListener;
+ private ImageView mButtonImageView;
+ private TextView mDescriptionTextView;
+ private Animator mFocusGainAnimator;
+ private Animator mFocusLoseAnimator;
+
+ private final OnFocusChangeListener mInternalFocusChangeListener =
+ new OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (hasFocus) {
+ if (mFocusLoseAnimator.isStarted()) {
+ mFocusLoseAnimator.cancel();
+ }
+ mFocusGainAnimator.start();
+ } else {
+ if (mFocusGainAnimator.isStarted()) {
+ mFocusGainAnimator.cancel();
+ }
+ mFocusLoseAnimator.start();
+ }
+
+ if (mFocusChangeListener != null) {
+ mFocusChangeListener.onFocusChange(v, hasFocus);
+ }
+ }
+ };
+
+ public PipControlButtonView(Context context) {
+ this(context, null, 0, 0);
+ }
+
+ public PipControlButtonView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0, 0);
+ }
+
+ public PipControlButtonView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public PipControlButtonView(
+ Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ LayoutInflater inflater = (LayoutInflater) getContext()
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(R.layout.tv_pip_control_button, this);
+
+ setOrientation(LinearLayout.VERTICAL);
+ setGravity(Gravity.CENTER);
+
+ mButtonImageView = (ImageView) findViewById(R.id.button);
+ mDescriptionTextView = (TextView) findViewById(R.id.desc);
+
+ int[] values = new int[] {android.R.attr.src, android.R.attr.text};
+ TypedArray typedArray =
+ context.obtainStyledAttributes(attrs, values, defStyleAttr, defStyleRes);
+
+ mButtonImageView.setImageDrawable(typedArray.getDrawable(0));
+ mDescriptionTextView.setText(typedArray.getText(1));
+
+ typedArray.recycle();
+ }
+
+ @Override
+ public void onFinishInflate() {
+ super.onFinishInflate();
+ mButtonImageView.setOnFocusChangeListener(mInternalFocusChangeListener);
+
+ mFocusGainAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_text_focus_gain_animation);
+ mFocusGainAnimator.setTarget(mDescriptionTextView);
+ mFocusLoseAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_text_focus_lose_animation);
+ mFocusLoseAnimator.setTarget(mDescriptionTextView);
+ }
+
+ @Override
+ public void setOnClickListener(OnClickListener listener) {
+ mButtonImageView.setOnClickListener(listener);
+ }
+
+ @Override
+ public void setOnFocusChangeListener(OnFocusChangeListener listener) {
+ mFocusChangeListener = listener;
+ }
+
+ /**
+ * Sets the drawable for the button with the given resource id.
+ */
+ public void setImageResource(int resId) {
+ mButtonImageView.setImageResource(resId);
+ }
+
+ /**
+ * Sets the text for description the with the given resource id.
+ */
+ public void setText(int resId) {
+ mDescriptionTextView.setText(resId);
+ }
+
+ @Override
+ public boolean isFocused() {
+ return mButtonImageView.isFocused();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
index 3f87611..d15799c 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
@@ -57,13 +57,9 @@
final PipManager mPipManager = PipManager.getInstance();
Listener mListener;
- View mFullButtonView;
- View mFullDescriptionView;
- View mPlayPauseView;
- ImageView mPlayPauseButtonImageView;
- TextView mPlayPauseDescriptionTextView;
- View mCloseButtonView;
- View mCloseDescriptionView;
+ PipControlButtonView mFullButtonView;
+ PipControlButtonView mCloseButtonView;
+ PipControlButtonView mPlayPauseButtonView;
private boolean mHasFocus;
private OnFocusChangeListener mOnChildFocusChangeListener;
@@ -75,13 +71,20 @@
}
};
- private PipManager.MediaListener mPipMediaListener = new PipManager.MediaListener() {
+ private final PipManager.MediaListener mPipMediaListener = new PipManager.MediaListener() {
@Override
public void onMediaControllerChanged() {
updateMediaController();
}
};
+ private final OnFocusChangeListener mFocusChangeListener = new OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ onChildViewFocusChanged();
+ }
+ };
+
public PipControlsView(Context context) {
this(context, null, 0, 0);
}
@@ -108,26 +111,30 @@
public void onFinishInflate() {
super.onFinishInflate();
- mFullButtonView = findViewById(R.id.full_button);
- mFullDescriptionView = findViewById(R.id.full_desc);
+ mFullButtonView = (PipControlButtonView) findViewById(R.id.full_button);
+ mFullButtonView.setOnFocusChangeListener(mFocusChangeListener);
mFullButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPipManager.movePipToFullscreen();
}
});
- mFullButtonView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+
+ mCloseButtonView = (PipControlButtonView) findViewById(R.id.close_button);
+ mCloseButtonView.setOnFocusChangeListener(mFocusChangeListener);
+ mCloseButtonView.setOnClickListener(new View.OnClickListener() {
@Override
- public void onFocusChange(View v, boolean hasFocus) {
- mFullDescriptionView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
- onChildViewFocusChanged();
+ public void onClick(View v) {
+ mPipManager.closePip();
+ if (mListener != null) {
+ mListener.onClosed();
+ }
}
});
- mPlayPauseView = findViewById(R.id.play_pause);
- mPlayPauseButtonImageView = (ImageView) findViewById(R.id.play_pause_button);
- mPlayPauseDescriptionTextView = (TextView) findViewById(R.id.play_pause_desc);
- mPlayPauseButtonImageView.setOnClickListener(new View.OnClickListener() {
+ mPlayPauseButtonView = (PipControlButtonView) findViewById(R.id.play_pause_button);
+ mPlayPauseButtonView.setOnFocusChangeListener(mFocusChangeListener);
+ mPlayPauseButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mMediaController == null || mMediaController.getPlaybackState() == null) {
@@ -143,33 +150,6 @@
// View will be updated later in {@link mMediaControllerCallback}
}
});
- mPlayPauseButtonImageView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- mPlayPauseDescriptionTextView.setVisibility(
- hasFocus ? View.VISIBLE : View.INVISIBLE);
- onChildViewFocusChanged();
- }
- });
-
- mCloseButtonView = findViewById(R.id.close_button);
- mCloseDescriptionView = findViewById(R.id.close_desc);
- mCloseButtonView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mPipManager.closePip();
- if (mListener != null) {
- mListener.onClosed();
- }
- }
- });
- mCloseButtonView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- mCloseDescriptionView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
- onChildViewFocusChanged();
- }
- });
}
@Override
@@ -206,15 +186,15 @@
private void updatePlayPauseView() {
int state = mPipManager.getPlaybackState();
if (state == PLAYBACK_STATE_UNAVAILABLE) {
- mPlayPauseView.setVisibility(View.GONE);
+ mPlayPauseButtonView.setVisibility(View.GONE);
} else {
- mPlayPauseView.setVisibility(View.VISIBLE);
+ mPlayPauseButtonView.setVisibility(View.VISIBLE);
if (state == PLAYBACK_STATE_PLAYING) {
- mPlayPauseButtonImageView.setImageResource(R.drawable.tv_pip_pause_button);
- mPlayPauseDescriptionTextView.setText(R.string.pip_pause);
+ mPlayPauseButtonView.setImageResource(R.drawable.ic_pause_white_24dp);
+ mPlayPauseButtonView.setText(R.string.pip_pause);
} else {
- mPlayPauseButtonImageView.setImageResource(R.drawable.tv_pip_play_button);
- mPlayPauseDescriptionTextView.setText(R.string.pip_play);
+ mPlayPauseButtonView.setImageResource(R.drawable.ic_play_arrow_white_24dp);
+ mPlayPauseButtonView.setText(R.string.pip_play);
}
}
}
@@ -229,7 +209,7 @@
private void onChildViewFocusChanged() {
// At this moment, hasFocus() returns true although there's no focused child.
boolean hasFocus = (mFullButtonView != null && mFullButtonView.isFocused())
- || (mPlayPauseButtonImageView != null && mPlayPauseButtonImageView.isFocused())
+ || (mPlayPauseButtonView != null && mPlayPauseButtonView.isFocused())
|| (mCloseButtonView != null && mCloseButtonView.isFocused());
if (mHasFocus != hasFocus) {
mHasFocus = hasFocus;
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
index 854e09d..542a935 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
@@ -16,10 +16,14 @@
package com.android.systemui.tv.pip;
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
import android.app.Activity;
import android.os.Bundle;
+import android.view.View;
import com.android.systemui.R;
+import com.android.systemui.Interpolators;
/**
* Activity to show the PIP menu to control PIP.
@@ -29,7 +33,9 @@
private final PipManager mPipManager = PipManager.getInstance();
- private PipControlsView mPipControlsView;
+ private Animator mFadeInAnimation;
+ private Animator mFadeOutAnimation;
+ private View mPipControlsView;
private boolean mRestorePipSizeWhenClose;
@Override
@@ -38,8 +44,14 @@
setContentView(R.layout.tv_pip_menu);
mPipManager.addListener(this);
- mPipControlsView = (PipControlsView) findViewById(R.id.pip_controls);
mRestorePipSizeWhenClose = true;
+ mPipControlsView = (PipControlsView) findViewById(R.id.pip_controls);
+ mFadeInAnimation = AnimatorInflater.loadAnimator(
+ this, R.anim.tv_pip_menu_fade_in_animation);
+ mFadeInAnimation.setTarget(mPipControlsView);
+ mFadeOutAnimation = AnimatorInflater.loadAnimator(
+ this, R.anim.tv_pip_menu_fade_out_animation);
+ mFadeOutAnimation.setTarget(mPipControlsView);
}
private void restorePipAndFinish() {
@@ -51,8 +63,15 @@
}
@Override
+ public void onResume() {
+ super.onResume();
+ mFadeInAnimation.start();
+ }
+
+ @Override
public void onPause() {
super.onPause();
+ mFadeOutAnimation.start();
restorePipAndFinish();
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
index 8b8c105..9c806f7 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
@@ -72,28 +72,20 @@
super.onFinishInflate();
int buttonsFocusGainAnim = R.anim.tv_pip_controls_buttons_in_recents_focus_gain_animation;
- int textFocusGainAnim = R.anim.tv_pip_controls_text_in_recents_focus_gain_animation;
mFocusGainAnimatorSet = new AnimatorSet();
mFocusGainAnimatorSet.playTogether(
loadAnimator(this, R.anim.tv_pip_controls_in_recents_focus_gain_animation),
loadAnimator(mFullButtonView,buttonsFocusGainAnim),
- loadAnimator(mPlayPauseButtonImageView, buttonsFocusGainAnim),
- loadAnimator(mCloseButtonView, buttonsFocusGainAnim),
- loadAnimator(mFullDescriptionView, textFocusGainAnim),
- loadAnimator(mPlayPauseDescriptionTextView, textFocusGainAnim),
- loadAnimator(mCloseDescriptionView, textFocusGainAnim));
+ loadAnimator(mPlayPauseButtonView, buttonsFocusGainAnim),
+ loadAnimator(mCloseButtonView, buttonsFocusGainAnim));
int buttonsFocusLoseAnim = R.anim.tv_pip_controls_buttons_in_recents_focus_lose_animation;
- int textFocusLoseAnim = R.anim.tv_pip_controls_text_in_recents_focus_lose_animation;
mFocusLoseAnimatorSet = new AnimatorSet();
mFocusLoseAnimatorSet.playTogether(
loadAnimator(this, R.anim.tv_pip_controls_in_recents_focus_lose_animation),
loadAnimator(mFullButtonView, buttonsFocusLoseAnim),
- loadAnimator(mPlayPauseButtonImageView, buttonsFocusLoseAnim),
- loadAnimator(mCloseButtonView, buttonsFocusLoseAnim),
- loadAnimator(mFullDescriptionView, textFocusLoseAnim),
- loadAnimator(mPlayPauseDescriptionTextView, textFocusLoseAnim),
- loadAnimator(mCloseDescriptionView, textFocusLoseAnim));
+ loadAnimator(mPlayPauseButtonView, buttonsFocusLoseAnim),
+ loadAnimator(mCloseButtonView, buttonsFocusLoseAnim));
Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
int pipControlsMarginTop = getContext().getResources().getDimensionPixelSize(
@@ -142,11 +134,8 @@
requestFocus();
setTranslationY(0);
setScaleXY(mFullButtonView, 1);
- setScaleXY(mPlayPauseButtonImageView, 1);
+ setScaleXY(mPlayPauseButtonView, 1);
setScaleXY(mCloseButtonView, 1);
- mFullDescriptionView.setAlpha(1);
- mPlayPauseDescriptionTextView.setAlpha(1);
- mCloseDescriptionView.setAlpha(1);
}
private void setScaleXY(View view, float scale) {
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
index 47cd8e5..c0e221f 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
@@ -16,8 +16,6 @@
package com.android.systemui.tv.pip;
-import android.animation.AnimatorInflater;
-import android.animation.AnimatorSet;
import android.content.Context;
import android.graphics.PixelFormat;
import android.util.Log;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 2ccc3fe..d8b3a97 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2206,6 +2206,12 @@
}
mLegacyTypeTracker.remove(nai, wasDefault);
rematchAllNetworksAndRequests(null, 0);
+ if (wasDefault && getDefaultNetwork() == null) {
+ // Log that we lost the default network and there is no replacement.
+ final int[] transportTypes = new int[0];
+ ConnectivityServiceChangeEvent.logEvent(NETID_UNSET, nai.network.netId,
+ transportTypes);
+ }
if (nai.created) {
// Tell netd to clean up the configuration for this network
// (routing rules, DNS, etc).
@@ -4427,9 +4433,9 @@
teardownUnneededNetwork(oldNetwork);
}
- private void makeDefault(NetworkAgentInfo newNetwork) {
+ private void makeDefault(NetworkAgentInfo newNetwork, NetworkAgentInfo prevNetwork) {
+ int prevNetId = (prevNetwork == null) ? NETID_UNSET : prevNetwork.network.netId;
if (DBG) log("Switching to new default network: " + newNetwork);
- ConnectivityServiceChangeEvent.logEvent(newNetwork.network.netId);
setupDataActivityTracking(newNetwork);
try {
mNetd.setDefaultNetId(newNetwork.network.netId);
@@ -4440,6 +4446,8 @@
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
updateTcpBufferSizes(newNetwork);
setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
+ ConnectivityServiceChangeEvent.logEvent(newNetwork.network.netId, prevNetId,
+ newNetwork.networkCapabilities.getTransportTypes());
}
// Handles a network appearing or improving its score.
@@ -4590,7 +4598,7 @@
}
if (isNewDefault) {
// Notify system services that this network is up.
- makeDefault(newNetwork);
+ makeDefault(newNetwork, oldDefaultNetwork);
synchronized (ConnectivityService.this) {
// have a new default network, release the transition wakelock in
// a second if it's held. The second pause is to allow apps
diff --git a/services/core/java/com/android/server/accounts/CryptoHelper.java b/services/core/java/com/android/server/accounts/CryptoHelper.java
index 2b59b74..2ade673 100644
--- a/services/core/java/com/android/server/accounts/CryptoHelper.java
+++ b/services/core/java/com/android/server/accounts/CryptoHelper.java
@@ -10,15 +10,12 @@
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
/**
* A crypto helper for encrypting and decrypting bundle with in-memory symmetric
@@ -30,15 +27,15 @@
private static final String KEY_CIPHER = "cipher";
private static final String KEY_MAC = "mac";
private static final String KEY_ALGORITHM = "AES";
+ private static final String KEY_IV = "iv";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static final String MAC_ALGORITHM = "HMACSHA256";
private static final int IV_LENGTH = 16;
private static CryptoHelper sInstance;
// Keys used for encrypting and decrypting data returned in a Bundle.
- private final SecretKeySpec mCipherKeySpec;
- private final SecretKeySpec mMacKeySpec;
- private final IvParameterSpec mIv;
+ private final SecretKey mEncryptionKey;
+ private final SecretKey mMacKey;
/* default */ synchronized static CryptoHelper getInstance() throws NoSuchAlgorithmException {
if (sInstance == null) {
@@ -49,18 +46,10 @@
private CryptoHelper() throws NoSuchAlgorithmException {
KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM);
- SecretKey skey = kgen.generateKey();
- mCipherKeySpec = new SecretKeySpec(skey.getEncoded(), KEY_ALGORITHM);
-
+ mEncryptionKey = kgen.generateKey();
+ // Use a different key for mac-ing than encryption/decryption.
kgen = KeyGenerator.getInstance(MAC_ALGORITHM);
- skey = kgen.generateKey();
- mMacKeySpec = new SecretKeySpec(skey.getEncoded(), MAC_ALGORITHM);
-
- // Create random iv
- byte[] iv = new byte[IV_LENGTH];
- SecureRandom secureRandom = new SecureRandom();
- secureRandom.nextBytes(iv);
- mIv = new IvParameterSpec(iv);
+ mMacKey = kgen.generateKey();
}
@NonNull
@@ -68,16 +57,19 @@
Preconditions.checkNotNull(bundle, "Cannot encrypt null bundle.");
Parcel parcel = Parcel.obtain();
bundle.writeToParcel(parcel, 0);
- byte[] bytes = parcel.marshall();
+ byte[] clearBytes = parcel.marshall();
parcel.recycle();
+ Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
+ cipher.init(Cipher.ENCRYPT_MODE, mEncryptionKey);
+ byte[] encryptedBytes = cipher.doFinal(clearBytes);
+ byte[] iv = cipher.getIV();
+ byte[] mac = createMac(encryptedBytes, iv);
+
Bundle encryptedBundle = new Bundle();
-
- byte[] cipher = encrypt(bytes);
- byte[] mac = createMac(cipher);
-
- encryptedBundle.putByteArray(KEY_CIPHER, cipher);
+ encryptedBundle.putByteArray(KEY_CIPHER, encryptedBytes);
encryptedBundle.putByteArray(KEY_MAC, mac);
+ encryptedBundle.putByteArray(KEY_IV, iv);
return encryptedBundle;
}
@@ -85,19 +77,18 @@
@Nullable
/* default */ Bundle decryptBundle(@NonNull Bundle bundle) throws GeneralSecurityException {
Preconditions.checkNotNull(bundle, "Cannot decrypt null bundle.");
- byte[] cipherArray = bundle.getByteArray(KEY_CIPHER);
- byte[] macArray = bundle.getByteArray(KEY_MAC);
-
- if (!verifyMac(cipherArray, macArray)) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Escrow mac mismatched!");
- }
+ byte[] iv = bundle.getByteArray(KEY_IV);
+ byte[] encryptedBytes = bundle.getByteArray(KEY_CIPHER);
+ byte[] mac = bundle.getByteArray(KEY_MAC);
+ if (!verifyMac(encryptedBytes, iv, mac)) {
+ Log.w(TAG, "Escrow mac mismatched!");
return null;
}
+ IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
- cipher.init(Cipher.DECRYPT_MODE, mCipherKeySpec, mIv);
- byte[] decryptedBytes = cipher.doFinal(cipherArray);
+ cipher.init(Cipher.DECRYPT_MODE, mEncryptionKey, ivSpec);
+ byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
Parcel decryptedParcel = Parcel.obtain();
decryptedParcel.unmarshall(decryptedBytes, 0, decryptedBytes.length);
@@ -108,9 +99,8 @@
return decryptedBundle;
}
- private boolean verifyMac(@Nullable byte[] cipherArray, @Nullable byte[] macArray)
+ private boolean verifyMac(@Nullable byte[] cipherArray, @Nullable byte[] iv, @Nullable byte[] macArray)
throws GeneralSecurityException {
-
if (cipherArray == null || cipherArray.length == 0 || macArray == null
|| macArray.length == 0) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -118,23 +108,29 @@
}
return false;
}
- Mac mac = Mac.getInstance(MAC_ALGORITHM);
- mac.init(mMacKeySpec);
- mac.update(cipherArray);
- return Arrays.equals(macArray, mac.doFinal());
+ return constantTimeArrayEquals(macArray, createMac(cipherArray, iv));
}
@NonNull
- private byte[] encrypt(@NonNull byte[] data) throws GeneralSecurityException {
- Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
- cipher.init(Cipher.ENCRYPT_MODE, mCipherKeySpec, mIv);
- return cipher.doFinal(data);
+ private byte[] createMac(@NonNull byte[] cipher, @NonNull byte[] iv) throws GeneralSecurityException {
+ Mac mac = Mac.getInstance(MAC_ALGORITHM);
+ mac.init(mMacKey);
+ mac.update(cipher);
+ mac.update(iv);
+ return mac.doFinal();
}
- @NonNull
- private byte[] createMac(@NonNull byte[] cipher) throws GeneralSecurityException {
- Mac mac = Mac.getInstance(MAC_ALGORITHM);
- mac.init(mMacKeySpec);
- return mac.doFinal(cipher);
+ private static boolean constantTimeArrayEquals(byte[] a, byte[] b) {
+ if (a == null || b == null) {
+ return a == b;
+ }
+ if (a.length != b.length) {
+ return false;
+ }
+ boolean isEqual = true;
+ for (int i = 0; i < b.length; i++) {
+ isEqual &= (a[i] == b[i]);
+ }
+ return isEqual;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4c75f50..04a63a1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17622,7 +17622,7 @@
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
- requiredPermissions, appOp, null, serialized, sticky,
+ requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 5ce451f..d8c0775 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -318,6 +318,7 @@
AccessibilityManager mAccessibilityManager;
BurnInProtectionHelper mBurnInProtectionHelper;
AppOpsManager mAppOpsManager;
+ private boolean mHasFeatureWatch;
// Vibrator pattern for haptic feedback of a long press.
long[] mLongPressVibePattern;
@@ -693,6 +694,7 @@
= new LogDecelerateInterpolator(100, 0);
private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
+
private static final int MSG_ENABLE_POINTER_LOCATION = 1;
private static final int MSG_DISABLE_POINTER_LOCATION = 2;
private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
@@ -1501,6 +1503,7 @@
mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+ mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
// Init display burn-in protection
boolean burnInProtectionEnabled = context.getResources().getBoolean(
@@ -5780,9 +5783,14 @@
}
private boolean shouldDispatchInputWhenNonInteractive() {
- // Send events to keyguard while the screen is on.
- if (isKeyguardShowingAndNotOccluded() && mDisplay != null
- && mDisplay.getState() != Display.STATE_OFF) {
+ final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
+
+ if (displayOff && !mHasFeatureWatch) {
+ return false;
+ }
+
+ // Send events to keyguard while the screen is on and it's showing.
+ if (isKeyguardShowingAndNotOccluded() && !displayOff) {
return true;
}
@@ -6695,7 +6703,7 @@
@Override public void run() {
if (mBootMsgDialog == null) {
int theme;
- if (mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH)) {
+ if (mHasFeatureWatch) {
theme = com.android.internal.R.style.Theme_Micro_Dialog_Alert;
} else if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 406dd56..804fa03 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -336,17 +336,17 @@
class ReceiveThread extends Thread {
private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH];
- private boolean stopped = false;
+ private volatile boolean mStopped = false;
public void halt() {
- stopped = true;
+ mStopped = true;
closeSockets(); // Interrupts the read() call the thread is blocked in.
}
@Override
public void run() {
if (DBG) Log.d(TAG, "Receive thread started");
- while (!stopped) {
+ while (!mStopped) {
int length = 0; // Or compiler can't tell it's initialized if a parse error occurs.
try {
length = Os.read(mPacketSock, mPacket, 0, mPacket.length);
@@ -355,7 +355,7 @@
if (DBG) Log.d(TAG, "Received packet: " + packet);
sendMessage(CMD_RECEIVED_PACKET, packet);
} catch (IOException|ErrnoException e) {
- if (!stopped) {
+ if (!mStopped) {
Log.e(TAG, "Read error", e);
}
DhcpClientEvent.logEvent(IpConnectivityEvent.IPCE_DHCP_RECV_ERROR,
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index c716cc8..59ebf1b 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -30,10 +30,12 @@
import android.net.RouteInfo;
import android.net.StaticIpConfiguration;
import android.net.dhcp.DhcpClient;
+import android.net.metrics.IpManagerEvent;
import android.os.INetworkManagementService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
@@ -52,6 +54,10 @@
import java.net.SocketException;
import java.util.Objects;
+import static android.net.metrics.IpConnectivityEvent.IPCE_IPMGR_PROVISIONING_OK;
+import static android.net.metrics.IpConnectivityEvent.IPCE_IPMGR_PROVISIONING_FAIL;
+import static android.net.metrics.IpConnectivityEvent.IPCE_IPMGR_COMPLETE_LIFECYCLE;
+
/**
* IpManager
@@ -264,6 +270,7 @@
private ProxyInfo mHttpProxy;
private ApfFilter mApfFilter;
private boolean mMulticastFiltering;
+ private long mStartTimeMillis;
/**
* Member variables accessed both from within the StateMachine thread
@@ -479,6 +486,12 @@
}
}
+ private void recordMetric(final int type) {
+ if (mStartTimeMillis <= 0) { Log.wtf(mTag, "Start time undefined!"); }
+ IpManagerEvent.logEvent(type, mInterfaceName,
+ SystemClock.elapsedRealtime() - mStartTimeMillis);
+ }
+
// For now: use WifiStateMachine's historical notion of provisioned.
private static boolean isProvisioned(LinkProperties lp) {
// For historical reasons, we should connect even if all we have is
@@ -554,11 +567,13 @@
switch (delta) {
case GAINED_PROVISIONING:
if (VDBG) { Log.d(mTag, "onProvisioningSuccess()"); }
+ recordMetric(IPCE_IPMGR_PROVISIONING_OK);
mCallback.onProvisioningSuccess(newLp);
break;
case LOST_PROVISIONING:
if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
+ recordMetric(IPCE_IPMGR_PROVISIONING_FAIL);
mCallback.onProvisioningFailure(newLp);
break;
@@ -734,6 +749,10 @@
}
resetLinkProperties();
+ if (mStartTimeMillis > 0) {
+ recordMetric(IPCE_IPMGR_COMPLETE_LIFECYCLE);
+ mStartTimeMillis = 0;
+ }
}
@Override
@@ -804,11 +823,16 @@
class StartedState extends State {
@Override
public void enter() {
+ mStartTimeMillis = SystemClock.elapsedRealtime();
+
mApfFilter = ApfFilter.maybeCreate(mConfiguration.mApfCapabilities, mNetworkInterface,
mCallback, mMulticastFiltering);
// TODO: investigate the effects of any multicast filtering racing/interfering with the
// rest of this IP configuration startup.
- if (mApfFilter == null) mCallback.setFallbackMulticastFilter(mMulticastFiltering);
+ if (mApfFilter == null) {
+ mCallback.setFallbackMulticastFilter(mMulticastFiltering);
+ }
+
// Set privacy extensions.
try {
mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
@@ -839,6 +863,7 @@
handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
} else {
if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
+ recordMetric(IPCE_IPMGR_PROVISIONING_FAIL);
mCallback.onProvisioningFailure(getLinkProperties());
transitionTo(mStoppingState);
}
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index af3175a..c8dbe02 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -26,6 +26,7 @@
import android.net.RouteInfo;
import android.net.metrics.IpReachabilityMonitorMessageEvent;
import android.net.metrics.IpReachabilityMonitorProbeEvent;
+import android.net.metrics.IpReachabilityMonitorLostEvent;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkErrorMessage;
import android.net.netlink.NetlinkMessage;
@@ -353,6 +354,7 @@
}
if (delta == ProvisioningChange.LOST_PROVISIONING) {
+ IpReachabilityMonitorLostEvent.logEvent(mInterfaceName);
final String logMsg = "FAILURE: LOST_PROVISIONING, " + msg;
Log.w(TAG, logMsg);
if (mCallback != null) {
@@ -521,7 +523,7 @@
final short msgType = neighMsg.getHeader().nlmsg_type;
final short nudState = ndMsg.ndm_state;
- IpReachabilityMonitorMessageEvent.logEvent(maybeGetInterfaceName(mInterfaceIndex),
+ IpReachabilityMonitorMessageEvent.logEvent(mInterfaceName,
destination.getHostAddress(), msgType, nudState);
final String eventMsg = "NeighborEvent{"
+ "elapsedMs=" + whenMs + ", "
@@ -553,11 +555,4 @@
}
}
}
-
- private String maybeGetInterfaceName(int index) {
- if (index == mInterfaceIndex) {
- return mInterfaceName;
- }
- return "ifindex-" + index;
- }
}