Merge "Expand NetworkMonitor metrics" into nyc-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index 0790a72..f017bb0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -26034,11 +26034,11 @@
     field public final int state;
   }
 
-  public final class ConnectivityServiceChangeEvent extends android.net.metrics.IpConnectivityEvent implements android.os.Parcelable {
+  public final class DefaultNetworkEvent extends android.net.metrics.IpConnectivityEvent implements android.os.Parcelable {
     method public int describeContents();
     method public static void logEvent(int, int[], int, boolean, boolean);
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.ConnectivityServiceChangeEvent> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.net.metrics.DefaultNetworkEvent> CREATOR;
     field public final int netId;
     field public final boolean prevIPv4;
     field public final boolean prevIPv6;
@@ -26112,9 +26112,10 @@
     field public static final int IPCE_IPMGR_PROVISIONING_FAIL = 4097; // 0x1001
     field public static final int IPCE_IPMGR_PROVISIONING_OK = 4096; // 0x1000
     field public static final int IPCE_IPRM_BASE = 0; // 0x0
-    field public static final int IPCE_IPRM_MESSAGE_RECEIVED = 1; // 0x1
-    field public static final int IPCE_IPRM_PROBE_RESULT = 0; // 0x0
-    field public static final int IPCE_IPRM_REACHABILITY_LOST = 2; // 0x2
+    field public static final int IPCE_IPRM_NUD_FAILED = 2; // 0x2
+    field public static final int IPCE_IPRM_PROBE_FAILURE = 1; // 0x1
+    field public static final int IPCE_IPRM_PROBE_STARTED = 0; // 0x0
+    field public static final int IPCE_IPRM_PROVISIONING_LOST = 3; // 0x3
     field public static final int IPCE_NETMON_BASE = 2048; // 0x800
     field public static final int IPCE_NETMON_CAPPORT_FOUND = 2052; // 0x804
     field public static final int IPCE_NETMON_CHECK_RESULT = 2049; // 0x801
@@ -26132,35 +26133,20 @@
     field public final java.lang.String ifName;
   }
 
-  public final class IpReachabilityMonitorLostEvent extends android.net.metrics.IpConnectivityEvent implements android.os.Parcelable {
+  public final class IpReachabilityEvent extends android.net.metrics.IpConnectivityEvent implements android.os.Parcelable {
     method public int describeContents();
-    method public static void logEvent(java.lang.String);
+    method public static void logNudFailed(java.lang.String);
+    method public static void logProbeEvent(java.lang.String, int);
+    method public static void logProvisioningLost(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.IpReachabilityMonitorLostEvent> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.net.metrics.IpReachabilityEvent> CREATOR;
+    field public static final int NUD_FAILED = 512; // 0x200
+    field public static final int PROBE = 256; // 0x100
+    field public static final int PROVISIONING_LOST = 768; // 0x300
+    field public final int eventType;
     field public final java.lang.String ifName;
   }
 
-  public final class IpReachabilityMonitorMessageEvent extends android.net.metrics.IpConnectivityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public static void logEvent(java.lang.String, java.lang.String, int, int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.IpReachabilityMonitorMessageEvent> CREATOR;
-    field public final java.lang.String destination;
-    field public final java.lang.String ifName;
-    field public final int msgType;
-    field public final int nudState;
-  }
-
-  public final class IpReachabilityMonitorProbeEvent extends android.net.metrics.IpConnectivityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public static void logEvent(java.lang.String, java.lang.String, boolean);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.IpReachabilityMonitorProbeEvent> CREATOR;
-    field public final java.lang.String destination;
-    field public final java.lang.String ifName;
-    field public final boolean success;
-  }
-
   public final class NetworkMonitorEvent extends android.net.metrics.IpConnectivityEvent implements android.os.Parcelable {
     ctor public NetworkMonitorEvent(android.os.Parcel);
     method public int describeContents();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 424d355..2f7c550 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -126,6 +126,19 @@
     public static final String META_HOME_ALTERNATE = "android.app.home.alternate";
 
     /**
+     * Result for IActivityManager.startVoiceActivity: active session is currently hidden.
+     * @hide
+     */
+    public static final int START_VOICE_HIDDEN_SESSION = -10;
+
+    /**
+     * Result for IActivityManager.startVoiceActivity: active session does not match
+     * the requesting token.
+     * @hide
+     */
+    public static final int START_VOICE_NOT_ACTIVE_SESSION = -9;
+
+    /**
      * Result for IActivityManager.startActivity: trying to start a background user
      * activity that shouldn't be displayed for all users.
      * @hide
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 4fca69a..95ea2a5 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1797,7 +1797,7 @@
         if (res >= ActivityManager.START_SUCCESS) {
             return;
         }
-        
+
         switch (res) {
             case ActivityManager.START_INTENT_NOT_RESOLVED:
             case ActivityManager.START_CLASS_NOT_FOUND:
@@ -1820,6 +1820,15 @@
             case ActivityManager.START_NOT_VOICE_COMPATIBLE:
                 throw new SecurityException(
                         "Starting under voice control not allowed for: " + intent);
+            case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
+                throw new IllegalStateException(
+                        "Session calling startVoiceActivity does not match active session");
+            case ActivityManager.START_VOICE_HIDDEN_SESSION:
+                throw new IllegalStateException(
+                        "Cannot start voice activity on a hidden session");
+            case ActivityManager.START_CANCELED:
+                throw new AndroidRuntimeException("Activity could not be started for "
+                        + intent);
             default:
                 throw new AndroidRuntimeException("Unknown error code "
                         + res + " when starting " + intent);
diff --git a/core/java/android/net/metrics/ConnectivityServiceChangeEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java
similarity index 69%
rename from core/java/android/net/metrics/ConnectivityServiceChangeEvent.java
rename to core/java/android/net/metrics/DefaultNetworkEvent.java
index fce68bb..f3c357b 100644
--- a/core/java/android/net/metrics/ConnectivityServiceChangeEvent.java
+++ b/core/java/android/net/metrics/DefaultNetworkEvent.java
@@ -24,8 +24,7 @@
  * {@hide}
  */
 @SystemApi
-public final class ConnectivityServiceChangeEvent extends IpConnectivityEvent
-        implements Parcelable {
+public final class DefaultNetworkEvent extends IpConnectivityEvent implements Parcelable {
     // The ID of the network that has become the new default or NETID_UNSET if none.
     public final int netId;
     // The list of transport types of the new default network, for example TRANSPORT_WIFI, as
@@ -37,7 +36,7 @@
     public final boolean prevIPv4;
     public final boolean prevIPv6;
 
-    private ConnectivityServiceChangeEvent(int netId, int[] transportTypes,
+    private DefaultNetworkEvent(int netId, int[] transportTypes,
                 int prevNetId, boolean prevIPv4, boolean prevIPv6) {
         this.netId = netId;
         this.transportTypes = transportTypes;
@@ -46,7 +45,7 @@
         this.prevIPv6 = prevIPv6;
     }
 
-    private ConnectivityServiceChangeEvent(Parcel in) {
+    private DefaultNetworkEvent(Parcel in) {
         this.netId = in.readInt();
         this.transportTypes = in.createIntArray();
         this.prevNetId = in.readInt();
@@ -66,21 +65,21 @@
         return 0;
     }
 
-    public static final Parcelable.Creator<ConnectivityServiceChangeEvent> CREATOR
-        = new Parcelable.Creator<ConnectivityServiceChangeEvent>() {
-        public ConnectivityServiceChangeEvent createFromParcel(Parcel in) {
-            return new ConnectivityServiceChangeEvent(in);
+    public static final Parcelable.Creator<DefaultNetworkEvent> CREATOR
+        = new Parcelable.Creator<DefaultNetworkEvent>() {
+        public DefaultNetworkEvent createFromParcel(Parcel in) {
+            return new DefaultNetworkEvent(in);
         }
 
-        public ConnectivityServiceChangeEvent[] newArray(int size) {
-            return new ConnectivityServiceChangeEvent[size];
+        public DefaultNetworkEvent[] newArray(int size) {
+            return new DefaultNetworkEvent[size];
         }
     };
 
-    public static void logEvent(int netId, int[] transportTypes,
-            int prevNetId, boolean prevIPv4, boolean prevIPv6) {
-        logEvent(IPCE_CONSRV_DEFAULT_NET_CHANGE,
-                new ConnectivityServiceChangeEvent(
-                        netId, transportTypes, prevNetId, prevIPv4, prevIPv6));
+    public static void logEvent(
+            int netId, int[] transports, int prevNetId, boolean hadIPv4, boolean hadIPv6) {
+        final DefaultNetworkEvent ev =
+                new DefaultNetworkEvent(netId, transports, prevNetId, hadIPv4, hadIPv6);
+        logEvent(IPCE_CONSRV_DEFAULT_NET_CHANGE, ev);
     }
 };
diff --git a/core/java/android/net/metrics/IpConnectivityEvent.java b/core/java/android/net/metrics/IpConnectivityEvent.java
index 1d6821e..0b5e354 100644
--- a/core/java/android/net/metrics/IpConnectivityEvent.java
+++ b/core/java/android/net/metrics/IpConnectivityEvent.java
@@ -39,9 +39,10 @@
     public static final int IPCE_IPMGR_BASE                = 4 * 1024;
     public static final int IPCE_DNS_BASE                  = 5 * 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_IPRM_PROBE_STARTED        = IPCE_IPRM_BASE + 0;
+    public static final int IPCE_IPRM_PROBE_FAILURE        = IPCE_IPRM_BASE + 1;
+    public static final int IPCE_IPRM_NUD_FAILED           = IPCE_IPRM_BASE + 2;
+    public static final int IPCE_IPRM_PROVISIONING_LOST    = IPCE_IPRM_BASE + 3;
 
     public static final int IPCE_DHCP_RECV_ERROR           = IPCE_DHCP_BASE + 0;
     public static final int IPCE_DHCP_PARSE_ERROR          = IPCE_DHCP_BASE + 1;
diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java
new file mode 100644
index 0000000..73dcb94
--- /dev/null
+++ b/core/java/android/net/metrics/IpReachabilityEvent.java
@@ -0,0 +1,84 @@
+/*
+ * 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.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * {@hide}
+ */
+@SystemApi
+public final class IpReachabilityEvent extends IpConnectivityEvent implements Parcelable {
+
+    public static final int PROBE             = 1 << 8;
+    public static final int NUD_FAILED        = 2 << 8;
+    public static final int PROVISIONING_LOST = 3 << 8;
+
+    public final String ifName;
+    // eventType byte format (MSB to LSB):
+    // byte 0: unused
+    // byte 1: unused
+    // byte 2: type of event: PROBE, NUD_FAILED, PROVISIONING_LOST
+    // byte 3: kernel errno from RTNetlink or IpReachabilityMonitor
+    public final int eventType;
+
+    private IpReachabilityEvent(String ifName, int eventType) {
+        this.ifName = ifName;
+        this.eventType = eventType;
+    }
+
+    private IpReachabilityEvent(Parcel in) {
+        this.ifName = in.readString();
+        this.eventType = in.readInt();
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(ifName);
+        out.writeInt(eventType);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Parcelable.Creator<IpReachabilityEvent> CREATOR
+        = new Parcelable.Creator<IpReachabilityEvent>() {
+        public IpReachabilityEvent createFromParcel(Parcel in) {
+            return new IpReachabilityEvent(in);
+        }
+
+        public IpReachabilityEvent[] newArray(int size) {
+            return new IpReachabilityEvent[size];
+        }
+    };
+
+    public static void logProbeEvent(String ifName, int nlErrorCode) {
+        final int tag = (nlErrorCode == 0) ? IPCE_IPRM_PROBE_STARTED : IPCE_IPRM_PROBE_FAILURE;
+        final int eventType = PROBE | (nlErrorCode & 0xFF);
+        logEvent(tag, new IpReachabilityEvent(ifName, eventType));
+    }
+
+    public static void logNudFailed(String ifName) {
+        logEvent(IPCE_IPRM_NUD_FAILED, new IpReachabilityEvent(ifName, NUD_FAILED));
+    }
+
+    public static void logProvisioningLost(String ifName) {
+        logEvent(IPCE_IPRM_PROVISIONING_LOST, new IpReachabilityEvent(ifName, PROVISIONING_LOST));
+    }
+};
diff --git a/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java b/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java
deleted file mode 100644
index 5215995..0000000
--- a/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * {@hide}
- */
-@SystemApi
-public final class IpReachabilityMonitorLostEvent extends IpConnectivityEvent
-        implements Parcelable {
-    public final String ifName;
-
-    private IpReachabilityMonitorLostEvent(String ifName) {
-        this.ifName = ifName;
-    }
-
-    private IpReachabilityMonitorLostEvent(Parcel in) {
-        this.ifName = in.readString();
-    }
-
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeString(ifName);
-    }
-
-    public int describeContents() {
-        return 0;
-    }
-
-    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) {
-        logEvent(IPCE_IPRM_REACHABILITY_LOST, new IpReachabilityMonitorLostEvent(ifName));
-    }
-};
diff --git a/core/java/android/net/metrics/IpReachabilityMonitorMessageEvent.java b/core/java/android/net/metrics/IpReachabilityMonitorMessageEvent.java
deleted file mode 100644
index 0ed8c1c..0000000
--- a/core/java/android/net/metrics/IpReachabilityMonitorMessageEvent.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * {@hide}
- */
-@SystemApi
-public final class IpReachabilityMonitorMessageEvent extends IpConnectivityEvent
-        implements Parcelable {
-    public final String ifName;
-    public final String destination;
-    public final int msgType;
-    public final int nudState;
-
-    private IpReachabilityMonitorMessageEvent(String ifName, String destination, int msgType,
-            int nudState) {
-        this.ifName = ifName;
-        this.destination = destination;
-        this.msgType = msgType;
-        this.nudState = nudState;
-    }
-
-    private IpReachabilityMonitorMessageEvent(Parcel in) {
-        this.ifName = in.readString();
-        this.destination = in.readString();
-        this.msgType = in.readInt();
-        this.nudState = in.readInt();
-    }
-
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeString(ifName);
-        out.writeString(destination);
-        out.writeInt(msgType);
-        out.writeInt(nudState);
-    }
-
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final Parcelable.Creator<IpReachabilityMonitorMessageEvent> CREATOR
-        = new Parcelable.Creator<IpReachabilityMonitorMessageEvent>() {
-        public IpReachabilityMonitorMessageEvent createFromParcel(Parcel in) {
-            return new IpReachabilityMonitorMessageEvent(in);
-        }
-
-        public IpReachabilityMonitorMessageEvent[] newArray(int size) {
-            return new IpReachabilityMonitorMessageEvent[size];
-        }
-    };
-
-    public static void logEvent(String ifName, String destination, int msgType, int nudState) {
-        logEvent(IPCE_IPRM_MESSAGE_RECEIVED,
-                new IpReachabilityMonitorMessageEvent(ifName, destination, msgType, nudState));
-    }
-};
diff --git a/core/java/android/net/metrics/IpReachabilityMonitorProbeEvent.java b/core/java/android/net/metrics/IpReachabilityMonitorProbeEvent.java
deleted file mode 100644
index a55c2b4..0000000
--- a/core/java/android/net/metrics/IpReachabilityMonitorProbeEvent.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * {@hide}
- */
-@SystemApi
-public final class IpReachabilityMonitorProbeEvent extends IpConnectivityEvent
-        implements Parcelable {
-    public final String ifName;
-    public final String destination;
-    public final boolean success;
-
-    private IpReachabilityMonitorProbeEvent(String ifName, String destination, boolean success) {
-        this.ifName = ifName;
-        this.destination = destination;
-        this.success = success;
-    }
-
-    private IpReachabilityMonitorProbeEvent(Parcel in) {
-        this.ifName = in.readString();
-        this.destination = in.readString();
-        this.success = in.readByte() > 0 ? true : false;
-    }
-
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeString(ifName);
-        out.writeString(destination);
-        out.writeByte((byte)(success ? 1 : 0));
-    }
-
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final Parcelable.Creator<IpReachabilityMonitorProbeEvent> CREATOR
-        = new Parcelable.Creator<IpReachabilityMonitorProbeEvent>() {
-        public IpReachabilityMonitorProbeEvent createFromParcel(Parcel in) {
-            return new IpReachabilityMonitorProbeEvent(in);
-        }
-
-        public IpReachabilityMonitorProbeEvent[] newArray(int size) {
-            return new IpReachabilityMonitorProbeEvent[size];
-        }
-    };
-
-    public static void logEvent(String ifName, String destination, boolean success) {
-        logEvent(IPCE_IPRM_PROBE_RESULT,
-                new IpReachabilityMonitorProbeEvent(ifName, destination, success));
-    }
-};
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 16d90de..c285acb 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1023,7 +1023,7 @@
     /**
      * Returns True if the device supports Sustained Performance Mode.
      * Applications Should check if the device supports this mode, before
-     * using {@link #SUSTAINED_PERFORMANCE_WAKE_LOCK}.
+     * using {@link android.view.Window#setSustainedPerformanceMode}.
      */
     public boolean isSustainedPerformanceModeSupported() {
         return mContext.getResources().getBoolean(
diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java
index 3e45309..9d296fa 100644
--- a/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -183,6 +183,9 @@
 
     @Override
     public void onRestoreFinished() {
-        mWallpaperHelper.onRestoreFinished();
+        // helper will be null following 'adb restore' or other full-data operation
+        if (mWallpaperHelper != null) {
+            mWallpaperHelper.onRestoreFinished();
+        }
     }
 }
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6776d3b..2040d7d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -497,14 +497,14 @@
     <string name="bugreport_option_interactive_title">Interactive report</string>
     <!-- Summary in the bugreport dialog for the interactive workflow. [CHAR LIMIT=NONE] -->
     <string name="bugreport_option_interactive_summary">Use this under most circumstances.
-        It allows you to track progress of the report and enter more details about the problem.
+        It allows you to track progress of the report, enter more details about the problem, and take screenshots.
         It might omit some less-used sections that take a long time to report.</string>
     <!-- Title in the bugreport dialog for the full workflow. Should fit in one line. [CHAR LIMIT=30] -->
     <string name="bugreport_option_full_title">Full report</string>
     <!-- Summary in the bugreport dialog for the full workflow. [CHAR LIMIT=NONE] -->
     <string name="bugreport_option_full_summary">Use this option for minimal system interference when
         your device is unresponsive or too slow, or when you need all report sections.
-        Does not take a screenshot or allow you to enter more details.</string>
+        Does not allow you to enter more details or take additional screenshots.</string>
     <!--  Toast message informing user in how many seconds a bugreport screenshot will be taken -->
     <plurals name="bugreport_countdown">
         <item quantity="one">Taking screenshot for bug report in <xliff:g id="number">%d</xliff:g> second.</item>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index ecdbe63..32fdb64 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -70,11 +70,7 @@
     }
 
     public boolean isDocumentEnabled(String docMimeType, int docFlags) {
-        if (isDirectory(docMimeType)) {
-            return true;
-        }
-
-        return MimePredicate.mimeMatches(mState.acceptMimes, docMimeType);
+        return true;
     }
 
     abstract void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch);
diff --git a/packages/SystemUI/res/layout/tv_pip_control_button.xml b/packages/SystemUI/res/layout/tv_pip_control_button.xml
index 0beeda1..f18a5da 100644
--- a/packages/SystemUI/res/layout/tv_pip_control_button.xml
+++ b/packages/SystemUI/res/layout/tv_pip_control_button.xml
@@ -38,5 +38,6 @@
         android:alpha="0"
         android:fontFamily="sans-serif"
         android:textSize="12sp"
-        android:textColor="#EEEEEE" />
+        android:textColor="#EEEEEE"
+        android:importantForAccessibility="no" />
 </merge>
diff --git a/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml b/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml
index 1e464d8..4a67000 100644
--- a/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml
+++ b/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml
@@ -23,7 +23,7 @@
     <com.android.systemui.tv.pip.PipRecentsControlsView
         android:id="@+id/pip_controls"
         android:layout_width="wrap_content"
-        android:layout_height="match_parent" />
+        android:layout_height="wrap_content" />
 
     <View
         android:id="@+id/recents"
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index 5e35d76..851ab77 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -67,7 +67,7 @@
         // If the phone is rotated to landscape, the calculations would be wrong if xdpi and ydpi
         // were to be used separately. Due negligible differences in xdpi and ydpi we can just
         // take the average.
-        // TODO: make this respect DPI changes.
+        // Note that xdpi and ydpi are the physical pixels per inch and are not affected by scaling.
         mDpi = (displayMetrics.xdpi + displayMetrics.ydpi) / 2.0f;
         mClassifierData = new ClassifierData(mDpi);
         mHistoryEvaluator = new HistoryEvaluator();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
index 7378102..4a8abf7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -26,6 +26,7 @@
 import android.view.View;
 import android.view.ViewTreeObserver.OnPreDrawListener;
 import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout.LayoutParams;
 
 import com.android.systemui.R;
@@ -131,6 +132,7 @@
                 @Override
                 public void onRecentsFocused() {
                     mRecentsView.requestFocus();
+                    mRecentsView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
                 }
             };
     private final View.OnFocusChangeListener mPipViewFocusChangeListener =
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 44a167b..9fd4b05 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -32,7 +32,6 @@
 import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.util.AttributeSet;
-import android.util.MutableInt;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.GestureDetector;
@@ -105,6 +104,8 @@
             new PathInterpolator(0.5f, 1f, 0.5f, 1f);
     private static final PathInterpolator DIM_INTERPOLATOR =
             new PathInterpolator(.23f, .87f, .52f, -0.11f);
+    private static final Interpolator IME_ADJUST_INTERPOLATOR =
+            new PathInterpolator(0.2f, 0f, 0.1f, 1f);
 
     private DividerHandleView mHandle;
     private View mBackground;
@@ -701,7 +702,7 @@
             resetBackground();
         } else if (mDockSide == WindowManager.DOCKED_TOP) {
             mBackground.setPivotY(0);
-            mBackground.setScaleY(MINIMIZE_DOCK_SCALE);
+            mBackground.setScaleY(ADJUSTED_FOR_IME_SCALE);
         }
         mAdjustedForIme = adjustedForIme;
     }
@@ -709,20 +710,20 @@
     public void setAdjustedForIme(boolean adjustedForIme, long animDuration) {
         updateDockSide();
         mHandle.animate()
-                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .setInterpolator(IME_ADJUST_INTERPOLATOR)
                 .setDuration(animDuration)
                 .alpha(adjustedForIme ? 0f : 1f)
                 .start();
         if (mDockSide == WindowManager.DOCKED_TOP) {
             mBackground.setPivotY(0);
             mBackground.animate()
-                    .scaleY(adjustedForIme ? MINIMIZE_DOCK_SCALE : 1f);
+                    .scaleY(adjustedForIme ? ADJUSTED_FOR_IME_SCALE : 1f);
         }
         if (!adjustedForIme) {
             mBackground.animate().withEndAction(mResetBackgroundRunnable);
         }
         mBackground.animate()
-                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .setInterpolator(IME_ADJUST_INTERPOLATOR)
                 .setDuration(animDuration)
                 .start();
         mAdjustedForIme = adjustedForIme;
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
index c65415e..bcf2f67 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
@@ -92,8 +92,8 @@
         TypedArray typedArray =
             context.obtainStyledAttributes(attrs, values, defStyleAttr, defStyleRes);
 
-        mButtonImageView.setImageDrawable(typedArray.getDrawable(0));
-        mDescriptionTextView.setText(typedArray.getText(1));
+        setImageResource(typedArray.getResourceId(0, 0));
+        setText(typedArray.getResourceId(1, 0));
 
         typedArray.recycle();
     }
@@ -132,6 +132,7 @@
      * Sets the text for description the with the given resource id.
      */
     public void setText(int resId) {
+        mButtonImageView.setContentDescription(getContext().getString(resId));
         mDescriptionTextView.setText(resId);
     }
 
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 d75561b..5ad0bf6 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
@@ -21,6 +21,7 @@
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManager;
 
@@ -141,6 +142,7 @@
 
         mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewFocusedLayoutParams);
         mPipControlsView.requestFocus();
+        mPipControlsView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
         mPipControlsView.startFocusGainAnimation();
     }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 4d7f82d..2a7d945 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -20,6 +20,7 @@
 import android.os.PowerManager;
 import android.util.Pools.SimplePool;
 import android.util.Slog;
+import android.util.SparseBooleanArray;
 import android.view.Choreographer;
 import android.view.InputDevice;
 import android.view.InputEvent;
@@ -637,10 +638,10 @@
     }
 
     /**
-     * Keeps state of stream of events from a keyboard device.
+     * Keeps state of streams of events from all keyboard devices.
      */
     private static class KeyboardEventStreamState extends EventStreamState {
-        private boolean mEventSequenceStarted;
+        private SparseBooleanArray mEventSequenceStartedMap = new SparseBooleanArray();
 
         public KeyboardEventStreamState() {
             reset();
@@ -649,17 +650,35 @@
         @Override
         final public void reset() {
             super.reset();
-            mEventSequenceStarted = false;
+            mEventSequenceStartedMap.clear();
         }
 
+        /*
+         * Key events from different devices may be interleaved. For example, the volume up and
+         * down keys can come from different device IDs.
+         */
+        @Override
+        public boolean updateDeviceId(int deviceId) {
+            return false;
+        }
+
+        // We manage all device ids simultaneously; there is no concept of validity.
+        @Override
+        public boolean deviceIdValid() {
+            return true;
+        }
+
+
         @Override
         final public boolean shouldProcessKeyEvent(KeyEvent event) {
-            // Wait for a down key event to start processing.
-            if (mEventSequenceStarted) {
+            // For each keyboard device, wait for a down event from a device to start processing
+            int deviceId = event.getDeviceId();
+            if (mEventSequenceStartedMap.get(deviceId, false)) {
                 return true;
             }
-            mEventSequenceStarted = event.getAction() == KeyEvent.ACTION_DOWN;
-            return mEventSequenceStarted;
+            boolean shouldProcess = event.getAction() == KeyEvent.ACTION_DOWN;
+            mEventSequenceStartedMap.put(deviceId, shouldProcess);
+            return shouldProcess;
         }
     }
 }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 71506be..0f21796 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -71,7 +71,7 @@
 import android.net.RouteInfo;
 import android.net.UidRange;
 import android.net.Uri;
-import android.net.metrics.ConnectivityServiceChangeEvent;
+import android.net.metrics.DefaultNetworkEvent;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -2217,7 +2217,7 @@
             rematchAllNetworksAndRequests(null, 0);
             if (wasDefault && getDefaultNetwork() == null) {
                 // Log that we lost the default network and there is no replacement.
-                logConnectivityServiceChangeEvent(null, nai);
+                logDefaultNetworkEvent(null, nai);
             }
             if (nai.created) {
                 // Tell netd to clean up the configuration for this network
@@ -4452,8 +4452,7 @@
         handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
         updateTcpBufferSizes(newNetwork);
         setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
-
-        logConnectivityServiceChangeEvent(newNetwork, prevNetwork);
+        logDefaultNetworkEvent(newNetwork, prevNetwork);
     }
 
     // Handles a network appearing or improving its score.
@@ -5075,21 +5074,24 @@
         return new NetworkMonitor(context, handler, nai, defaultRequest);
     }
 
-    private static void logConnectivityServiceChangeEvent(
-            NetworkAgentInfo next, NetworkAgentInfo prev) {
-        final int newNetId = (next == null) ? NETID_UNSET : next.network.netId;
-        final int[] newTransportTypes = (next == null)
-                ? new int[0]
-                : next.networkCapabilities.getTransportTypes();
+    private static void logDefaultNetworkEvent(NetworkAgentInfo newNai, NetworkAgentInfo prevNai) {
+        int newNetid = NETID_UNSET;
+        int prevNetid = NETID_UNSET;
+        int[] transports = new int[0];
+        boolean hadIPv4 = false;
+        boolean hadIPv6 = false;
 
-        final int oldNetId = (prev == null) ? NETID_UNSET : prev.network.netId;
-        final boolean hadIPv4 = (prev != null) &&
-                prev.linkProperties.hasIPv4Address() &&
-                prev.linkProperties.hasIPv4DefaultRoute();
-        final boolean hadIPv6 = (prev != null) &&
-                prev.linkProperties.hasGlobalIPv6Address() &&
-                prev.linkProperties.hasIPv6DefaultRoute();
-        ConnectivityServiceChangeEvent.logEvent(newNetId, newTransportTypes,
-                oldNetId, hadIPv4, hadIPv6);
+        if (newNai != null) {
+            newNetid = newNai.network.netId;
+            transports = newNai.networkCapabilities.getTransportTypes();
+        }
+        if (prevNai != null) {
+            prevNetid = prevNai.network.netId;
+            final LinkProperties lp = prevNai.linkProperties;
+            hadIPv4 = lp.hasIPv4Address() && lp.hasIPv4DefaultRoute();
+            hadIPv6 = lp.hasGlobalIPv6Address() && lp.hasIPv6DefaultRoute();
+        }
+
+        DefaultNetworkEvent.logEvent(newNetid, transports, prevNetid, hadIPv4, hadIPv6);
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9994af3..6ff09b1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1805,6 +1805,16 @@
         return true;
     }
 
+    private static boolean excludeWindowTypeFromTapOutTask(int windowType) {
+        switch (windowType) {
+            case TYPE_STATUS_BAR:
+            case TYPE_NAVIGATION_BAR:
+            case TYPE_INPUT_METHOD_DIALOG:
+                return true;
+        }
+        return false;
+    }
+
     public int addWindow(Session session, IWindow client, int seq,
             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
             Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
@@ -2003,7 +2013,7 @@
 
             res = WindowManagerGlobal.ADD_OKAY;
 
-            if (type == TYPE_STATUS_BAR || type == TYPE_NAVIGATION_BAR) {
+            if (excludeWindowTypeFromTapOutTask(type)) {
                 displayContent.mTapExcludedWindows.add(win);
             }
 
@@ -2395,7 +2405,7 @@
         }
 
         final int type = win.mAttrs.type;
-        if (type == TYPE_STATUS_BAR || type == TYPE_NAVIGATION_BAR) {
+        if (excludeWindowTypeFromTapOutTask(type)) {
             final DisplayContent displaycontent = win.getDisplayContent();
             displaycontent.mTapExcludedWindows.remove(win);
         }
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index c8dbe02..27600a7 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -24,9 +24,7 @@
 import android.net.LinkProperties.ProvisioningChange;
 import android.net.ProxyInfo;
 import android.net.RouteInfo;
-import android.net.metrics.IpReachabilityMonitorMessageEvent;
-import android.net.metrics.IpReachabilityMonitorProbeEvent;
-import android.net.metrics.IpReachabilityMonitorLostEvent;
+import android.net.metrics.IpReachabilityEvent;
 import android.net.netlink.NetlinkConstants;
 import android.net.netlink.NetlinkErrorMessage;
 import android.net.netlink.NetlinkMessage;
@@ -168,47 +166,54 @@
      * Make the kernel perform neighbor reachability detection (IPv4 ARP or IPv6 ND)
      * for the given IP address on the specified interface index.
      *
-     * @return true, if the request was successfully passed to the kernel; false otherwise.
+     * @return 0 if the request was successfully passed to the kernel; otherwise return
+     *         a non-zero error code.
      */
-    public static boolean probeNeighbor(int ifIndex, InetAddress ip) {
-        final long IO_TIMEOUT = 300L;
+    private static int probeNeighbor(int ifIndex, InetAddress ip) {
         final String msgSnippet = "probing ip=" + ip.getHostAddress() + "%" + ifIndex;
         if (DBG) { Log.d(TAG, msgSnippet); }
 
         final byte[] msg = RtNetlinkNeighborMessage.newNewNeighborMessage(
                 1, ip, StructNdMsg.NUD_PROBE, ifIndex, null);
-        boolean returnValue = false;
 
+        int errno = -OsConstants.EPROTO;
         try (NetlinkSocket nlSocket = new NetlinkSocket(OsConstants.NETLINK_ROUTE)) {
+            final long IO_TIMEOUT = 300L;
             nlSocket.connectToKernel();
             nlSocket.sendMessage(msg, 0, msg.length, IO_TIMEOUT);
             final ByteBuffer bytes = nlSocket.recvMessage(IO_TIMEOUT);
+            // recvMessage() guaranteed to not return null if it did not throw.
             final NetlinkMessage response = NetlinkMessage.parse(bytes);
             if (response != null && response instanceof NetlinkErrorMessage &&
-                    (((NetlinkErrorMessage) response).getNlMsgError() != null) &&
-                    (((NetlinkErrorMessage) response).getNlMsgError().error == 0)) {
-                returnValue = true;
-            } else {
-                String errmsg;
-                if (bytes == null) {
-                    errmsg = "null recvMessage";
-                } else if (response == null) {
-                    bytes.position(0);
-                    errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
-                } else {
+                    (((NetlinkErrorMessage) response).getNlMsgError() != null)) {
+                errno = ((NetlinkErrorMessage) response).getNlMsgError().error;
+                if (errno != 0) {
                     // TODO: consider ignoring EINVAL (-22), which appears to be
                     // normal when probing a neighbor for which the kernel does
                     // not already have / no longer has a link layer address.
+                    Log.e(TAG, "Error " + msgSnippet + ", errmsg=" + response.toString());
+                }
+            } else {
+                String errmsg;
+                if (response == null) {
+                    bytes.position(0);
+                    errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
+                } else {
                     errmsg = response.toString();
                 }
                 Log.e(TAG, "Error " + msgSnippet + ", errmsg=" + errmsg);
             }
-        } catch (ErrnoException | InterruptedIOException | SocketException e) {
-            Log.d(TAG, "Error " + msgSnippet, e);
+        } catch (ErrnoException e) {
+            Log.e(TAG, "Error " + msgSnippet, e);
+            errno = -e.errno;
+        } catch (InterruptedIOException e) {
+            Log.e(TAG, "Error " + msgSnippet, e);
+            errno = -OsConstants.ETIMEDOUT;
+        } catch (SocketException e) {
+            Log.e(TAG, "Error " + msgSnippet, e);
+            errno = -OsConstants.EIO;
         }
-        IpReachabilityMonitorProbeEvent.logEvent("ifindex-" + ifIndex, ip.getHostAddress(),
-                returnValue);
-        return returnValue;
+        return errno;
     }
 
     public IpReachabilityMonitor(Context context, String ifName, Callback callback)
@@ -354,7 +359,7 @@
         }
 
         if (delta == ProvisioningChange.LOST_PROVISIONING) {
-            IpReachabilityMonitorLostEvent.logEvent(mInterfaceName);
+            IpReachabilityEvent.logProvisioningLost(mInterfaceName);
             final String logMsg = "FAILURE: LOST_PROVISIONING, " + msg;
             Log.w(TAG, logMsg);
             if (mCallback != null) {
@@ -362,6 +367,8 @@
                 // an InetAddress argument.
                 mCallback.notifyLost(ip, logMsg);
             }
+        } else {
+            IpReachabilityEvent.logNudFailed(mInterfaceName);
         }
     }
 
@@ -385,7 +392,8 @@
             if (!stillRunning()) {
                 break;
             }
-            probeNeighbor(mInterfaceIndex, target);
+            final int returnValue = probeNeighbor(mInterfaceIndex, target);
+            IpReachabilityEvent.logProbeEvent(mInterfaceName, returnValue);
         }
     }
 
@@ -523,8 +531,6 @@
 
             final short msgType = neighMsg.getHeader().nlmsg_type;
             final short nudState = ndMsg.ndm_state;
-            IpReachabilityMonitorMessageEvent.logEvent(mInterfaceName,
-                    destination.getHostAddress(), msgType, nudState);
             final String eventMsg = "NeighborEvent{"
                     + "elapsedMs=" + whenMs + ", "
                     + destination.getHostAddress() + ", "
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 1e9db18..3f9da4c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -183,11 +183,11 @@
         try {
             if (mActiveSession == null || token != mActiveSession.mToken) {
                 Slog.w(TAG, "startVoiceActivity does not match active session");
-                return ActivityManager.START_CANCELED;
+                return ActivityManager.START_VOICE_NOT_ACTIVE_SESSION;
             }
             if (!mActiveSession.mShown) {
                 Slog.w(TAG, "startVoiceActivity not allowed on hidden session");
-                return ActivityManager.START_CANCELED;
+                return ActivityManager.START_VOICE_HIDDEN_SESSION;
             }
             intent = new Intent(intent);
             intent.addCategory(Intent.CATEGORY_VOICE);
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index 84883d8..03ce2d8 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -151,12 +151,24 @@
      * @return if the record is valid
      */
     public boolean isValid() {
-        int totalTxTimeMs = 0;
-        int txTime [] = getTxTimeMillis();
-        for (int i = 0; i < TX_POWER_LEVELS; i++) {
-            totalTxTimeMs += txTime[i];
+        for (int txVal : getTxTimeMillis()) {
+            if(txVal < 0) {
+                return false;
+            }
         }
-        return ((getIdleTimeMillis() >= 0) && (totalTxTimeMs >= 0)
-                && (getSleepTimeMillis() >= 0) && (getIdleTimeMillis() >= 0));
+
+        return ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0)
+                && (getRxTimeMillis() >= 0) && (getEnergyUsed() >= 0) && !isEmpty());
+    }
+
+    private boolean isEmpty() {
+        for (int txVal : getTxTimeMillis()) {
+            if(txVal != 0) {
+                return false;
+            }
+        }
+
+        return ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0)
+                && (getRxTimeMillis() == 0) && (getEnergyUsed() == 0));
     }
 }