Merge "Fix package install flow w.r.t. dexopt"
diff --git a/Android.mk b/Android.mk
index c0c025b..a69170f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -529,11 +529,13 @@
 	telephony/java/com/android/ims/internal/IImsService.aidl \
 	telephony/java/com/android/ims/internal/IImsServiceController.aidl \
 	telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl \
+        telephony/java/com/android/ims/internal/IImsSmsFeature.aidl \
 	telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl \
 	telephony/java/com/android/ims/internal/IImsUt.aidl \
 	telephony/java/com/android/ims/internal/IImsUtListener.aidl \
 	telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl \
 	telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl \
+        telephony/java/com/android/ims/internal/ISmsListener.aidl \
         telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl \
         telephony/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl \
         telephony/java/com/android/ims/internal/uce/options/IOptionsService.aidl \
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/PaintMeasureTextTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/PaintMeasureTextTest.java
index b81908c..b9ee613 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/PaintMeasureTextTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/PaintMeasureTextTest.java
@@ -80,11 +80,11 @@
         }
 
         while (state.keepRunning()) {
-            state.pauseTiming();
             if (mCacheMode == DONT_USE_CACHE) {
+                state.pauseTiming();
                 Canvas.freeTextLayoutCaches();
+                state.resumeTiming();
             }
-            state.resumeTiming();
 
             paint.measureText(mText);
         }
diff --git a/api/current.txt b/api/current.txt
index ed14b0e..182dd3a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -33140,6 +33140,7 @@
   public final class AlarmClock {
     ctor public AlarmClock();
     field public static final java.lang.String ACTION_DISMISS_ALARM = "android.intent.action.DISMISS_ALARM";
+    field public static final java.lang.String ACTION_DISMISS_TIMER = "android.intent.action.DISMISS_TIMER";
     field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
     field public static final java.lang.String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
     field public static final java.lang.String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 20e7c60..e0d9ce7 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -91,6 +91,8 @@
         CpuTimePerFreqPulled cpu_time_per_freq_pulled = 1008;
         CpuTimePerUidPulled cpu_time_per_uid_pulled = 1009;
         CpuTimePerUidFreqPulled cpu_time_per_uid_freq_pulled = 1010;
+        WifiActivityEnergyInfoPulled wifi_activity_energy_info_pulled = 1011;
+        ModemActivityInfoPulled modem_activity_info_pulled = 1012;
     }
 }
 
@@ -699,7 +701,7 @@
     optional int32 user = 7;
 }
 
-/*
+/**
  * Logs activity going to foreground or background
  *
  * Logged from:
@@ -839,7 +841,7 @@
     optional int64 time = 4;
 }
 
-/*
+/**
  * Pulls PowerStatePlatformSleepState.
  *
  * Definition here:
@@ -899,7 +901,7 @@
     optional int32 is_create = 3;
 }
 
-/*
+/**
  * Pulls Cpu time per frequency.
  * Note: this should be pulled for gauge metric only, without condition.
  * The puller keeps internal state of last values. It should not be pulled by
@@ -916,7 +918,7 @@
     optional uint64 time = 3;
 }
 
-/*
+/**
  * Pulls Cpu Time Per Uid.
  * Note that isolated process uid time should be attributed to host uids.
  */
@@ -965,3 +967,56 @@
     // The destination port if this was a TCP or UDP packet.
     optional int32 destination_port = 9;
 }
+
+/**
+ * Pulls Wifi Controller Activity Energy Info
+ */
+message WifiActivityEnergyInfoPulled {
+    // timestamp(wall clock) of record creation
+    optional uint64 timestamp_ms = 1;
+    // stack reported state
+    // TODO: replace this with proto enum
+    optional int32 stack_state = 2;
+    // tx time in ms
+    optional uint64 controller_tx_time_ms = 3;
+    // rx time in ms
+    optional uint64 controller_rx_time_ms = 4;
+    // idle time in ms
+    optional uint64 controller_idle_time_ms = 5;
+    // product of current(mA), voltage(V) and time(ms)
+    optional uint64 controller_energy_used = 6;
+}
+
+/**
+ * Pulls Modem Activity Energy Info
+ */
+message ModemActivityInfoPulled {
+    // timestamp(wall clock) of record creation
+    optional uint64 timestamp_ms = 1;
+    // sleep time in ms.
+    optional uint64 sleep_time_ms = 2;
+    // idle time in ms
+    optional uint64 controller_idle_time_ms = 3;
+    /**
+     * Tx power index
+     * index 0 = tx_power < 0dBm
+     * index 1 = 0dBm < tx_power < 5dBm
+     * index 2 = 5dBm < tx_power < 15dBm
+     * index 3 = 15dBm < tx_power < 20dBm
+     * index 4 = tx_power > 20dBm
+     */
+    // tx time in ms at power level 0
+    optional uint64 controller_tx_time_pl0_ms = 4;
+    // tx time in ms at power level 1
+    optional uint64 controller_tx_time_pl1_ms = 5;
+    // tx time in ms at power level 2
+    optional uint64 controller_tx_time_pl2_ms = 6;
+    // tx time in ms at power level 3
+    optional uint64 controller_tx_time_pl3_ms = 7;
+    // tx time in ms at power level 4
+    optional uint64 controller_tx_time_pl4_ms = 8;
+    // rx time in ms at power level 5
+    optional uint64 controller_rx_time_ms = 9;
+    // product of current(mA), voltage(V) and time(ms)
+    optional uint64 energy_used = 10;
+}
diff --git a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java
index 5b59c21..fe3d86d 100644
--- a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java
+++ b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java
@@ -110,113 +110,7 @@
                 log.getEventMetrics();
         for (StatsLog.EventMetricData event : eventMetricDataWrapper.getDataList()) {
             sb.append(getDateStr(event.getTimestampNanos())).append(": ");
-            switch (event.getAtom().getPushedCase()) {
-                case SETTING_CHANGED:
-                    sb.append("SETTING_CHANGED\n");
-                    break;
-                case SYNC_STATE_CHANGED:
-                    sb.append("SYNC_STATE_CHANGED\n");
-                    break;
-                case AUDIO_STATE_CHANGED:
-                    sb.append("AUDIO_STATE_CHANGED\n");
-                    break;
-                case CAMERA_STATE_CHANGED:
-                    sb.append("CAMERA_STATE_CHANGED\n");
-                    break;
-                case ISOLATED_UID_CHANGED:
-                    sb.append("ISOLATED_UID_CHANGED\n");
-                    break;
-                case SCREEN_STATE_CHANGED:
-                    sb.append("SCREEN_STATE_CHANGED\n");
-                    break;
-                case SENSOR_STATE_CHANGED:
-                    sb.append("SENSOR_STATE_CHANGED\n");
-                    break;
-                case BATTERY_LEVEL_CHANGED:
-                    sb.append("BATTERY_LEVEL_CHANGED\n");
-                    break;
-                case PLUGGED_STATE_CHANGED:
-                    sb.append("PLUGGED_STATE_CHANGED\n");
-                    break;
-                case WAKEUP_ALARM_OCCURRED:
-                    sb.append("WAKEUP_ALARM_OCCURRED\n");
-                    break;
-                case BLE_SCAN_STATE_CHANGED:
-                    sb.append("BLE_SCAN_STATE_CHANGED\n");
-                    break;
-                case CHARGING_STATE_CHANGED:
-                    sb.append("CHARGING_STATE_CHANGED\n");
-                    break;
-                case GPS_SCAN_STATE_CHANGED:
-                    sb.append("GPS_SCAN_STATE_CHANGED\n");
-                    break;
-                case KERNEL_WAKEUP_REPORTED:
-                    sb.append("KERNEL_WAKEUP_REPORTED\n");
-                    break;
-                case WAKELOCK_STATE_CHANGED:
-                    sb.append("WAKELOCK_STATE_CHANGED\n");
-                    break;
-                case WIFI_LOCK_STATE_CHANGED:
-                    sb.append("WIFI_LOCK_STATE_CHANGED\n");
-                    break;
-                case WIFI_SCAN_STATE_CHANGED:
-                    sb.append("WIFI_SCAN_STATE_CHANGED\n");
-                    break;
-                case BLE_SCAN_RESULT_RECEIVED:
-                    sb.append("BLE_SCAN_RESULT_RECEIVED\n");
-                    break;
-                case DEVICE_ON_STATUS_CHANGED:
-                    sb.append("DEVICE_ON_STATUS_CHANGED\n");
-                    break;
-                case FLASHLIGHT_STATE_CHANGED:
-                    sb.append("FLASHLIGHT_STATE_CHANGED\n");
-                    break;
-                case SCREEN_BRIGHTNESS_CHANGED:
-                    sb.append("SCREEN_BRIGHTNESS_CHANGED\n");
-                    break;
-                case UID_PROCESS_STATE_CHANGED:
-                    sb.append("UID_PROCESS_STATE_CHANGED\n");
-                    break;
-                case UID_WAKELOCK_STATE_CHANGED:
-                    sb.append("UID_WAKELOCK_STATE_CHANGED\n");
-                    break;
-                case DEVICE_TEMPERATURE_REPORTED:
-                    sb.append("DEVICE_TEMPERATURE_REPORTED\n");
-                    break;
-                case SCHEDULED_JOB_STATE_CHANGED:
-                    sb.append("SCHEDULED_JOB_STATE_CHANGED\n");
-                    break;
-                case MEDIA_CODEC_ACTIVITY_CHANGED:
-                    sb.append("MEDIA_CODEC_ACTIVITY_CHANGED\n");
-                    break;
-                case WIFI_SIGNAL_STRENGTH_CHANGED:
-                    sb.append("WIFI_SIGNAL_STRENGTH_CHANGED\n");
-                    break;
-                case PHONE_SIGNAL_STRENGTH_CHANGED:
-                    sb.append("PHONE_SIGNAL_STRENGTH_CHANGED\n");
-                    break;
-                case DEVICE_IDLE_MODE_STATE_CHANGED:
-                    sb.append("DEVICE_IDLE_MODE_STATE_CHANGED\n");
-                    break;
-                case BATTERY_SAVER_MODE_STATE_CHANGED:
-                    sb.append("BATTERY_SAVER_MODE_STATE_CHANGED\n");
-                    break;
-                case PROCESS_LIFE_CYCLE_STATE_CHANGED:
-                    sb.append("PROCESS_LIFE_CYCLE_STATE_CHANGED\n");
-                    break;
-                case ACTIVITY_FOREGROUND_STATE_CHANGED:
-                    sb.append("ACTIVITY_FOREGROUND_STATE_CHANGED\n");
-                    break;
-                case BLE_UNOPTIMIZED_SCAN_STATE_CHANGED:
-                    sb.append("BLE_UNOPTIMIZED_SCAN_STATE_CHANGED\n");
-                    break;
-                case LONG_PARTIAL_WAKELOCK_STATE_CHANGED:
-                    sb.append("LONG_PARTIAL_WAKELOCK_STATE_CHANGED\n");
-                    break;
-                case PUSHED_NOT_SET:
-                    sb.append("PUSHED_NOT_SET\n");
-                    break;
-            }
+            sb.append(event.getAtom().getPushedCase().toString()).append("\n");
         }
     }
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ffd012d..b84833b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -108,6 +108,7 @@
 import android.util.Slog;
 import android.util.SparseIntArray;
 import android.util.SuperNotCalledException;
+import android.util.proto.ProtoOutputStream;
 import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.ThreadedRenderer;
@@ -131,6 +132,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.org.conscrypt.OpenSSLSocketImpl;
 import com.android.org.conscrypt.TrustedCertificateStore;
+import com.android.server.am.proto.MemInfoProto;
 
 import dalvik.system.BaseDexClassLoader;
 import dalvik.system.CloseGuard;
@@ -2259,6 +2261,167 @@
         }
     }
 
+    /**
+     * Dump heap info to proto.
+     *
+     * @param hasSwappedOutPss determines whether to use dirtySwap or dirtySwapPss
+     */
+    private static void dumpHeap(ProtoOutputStream proto, long fieldId, String name,
+            int pss, int cleanPss, int sharedDirty, int privateDirty,
+            int sharedClean, int privateClean,
+            boolean hasSwappedOutPss, int dirtySwap, int dirtySwapPss) {
+        final long token = proto.start(fieldId);
+
+        proto.write(MemInfoProto.NativeProcess.MemoryInfo.NAME, name);
+        proto.write(MemInfoProto.NativeProcess.MemoryInfo.TOTAL_PSS_KB, pss);
+        proto.write(MemInfoProto.NativeProcess.MemoryInfo.CLEAN_PSS_KB, cleanPss);
+        proto.write(MemInfoProto.NativeProcess.MemoryInfo.SHARED_DIRTY_KB, sharedDirty);
+        proto.write(MemInfoProto.NativeProcess.MemoryInfo.PRIVATE_DIRTY_KB, privateDirty);
+        proto.write(MemInfoProto.NativeProcess.MemoryInfo.SHARED_CLEAN_KB, sharedClean);
+        proto.write(MemInfoProto.NativeProcess.MemoryInfo.PRIVATE_CLEAN_KB, privateClean);
+        if (hasSwappedOutPss) {
+            proto.write(MemInfoProto.NativeProcess.MemoryInfo.DIRTY_SWAP_PSS_KB, dirtySwapPss);
+        } else {
+            proto.write(MemInfoProto.NativeProcess.MemoryInfo.DIRTY_SWAP_KB, dirtySwap);
+        }
+
+        proto.end(token);
+    }
+
+    /**
+     * Dump mem info data to proto.
+     */
+    public static void dumpMemInfoTable(ProtoOutputStream proto, Debug.MemoryInfo memInfo,
+            boolean dumpDalvik, boolean dumpSummaryOnly,
+            long nativeMax, long nativeAllocated, long nativeFree,
+            long dalvikMax, long dalvikAllocated, long dalvikFree) {
+
+        if (!dumpSummaryOnly) {
+            final long nhToken = proto.start(MemInfoProto.NativeProcess.NATIVE_HEAP);
+            dumpHeap(proto, MemInfoProto.NativeProcess.HeapInfo.MEM_INFO, "Native Heap",
+                    memInfo.nativePss, memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
+                    memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
+                    memInfo.nativePrivateClean, memInfo.hasSwappedOutPss,
+                    memInfo.nativeSwappedOut, memInfo.nativeSwappedOutPss);
+            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_SIZE_KB, nativeMax);
+            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_ALLOC_KB, nativeAllocated);
+            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_FREE_KB, nativeFree);
+            proto.end(nhToken);
+
+            final long dvToken = proto.start(MemInfoProto.NativeProcess.DALVIK_HEAP);
+            dumpHeap(proto, MemInfoProto.NativeProcess.HeapInfo.MEM_INFO, "Dalvik Heap",
+                    memInfo.dalvikPss, memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
+                    memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
+                    memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss,
+                    memInfo.dalvikSwappedOut, memInfo.dalvikSwappedOutPss);
+            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_SIZE_KB, dalvikMax);
+            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_ALLOC_KB, dalvikAllocated);
+            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_FREE_KB, dalvikFree);
+            proto.end(dvToken);
+
+            int otherPss = memInfo.otherPss;
+            int otherSwappablePss = memInfo.otherSwappablePss;
+            int otherSharedDirty = memInfo.otherSharedDirty;
+            int otherPrivateDirty = memInfo.otherPrivateDirty;
+            int otherSharedClean = memInfo.otherSharedClean;
+            int otherPrivateClean = memInfo.otherPrivateClean;
+            int otherSwappedOut = memInfo.otherSwappedOut;
+            int otherSwappedOutPss = memInfo.otherSwappedOutPss;
+
+            for (int i = 0; i < Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
+                final int myPss = memInfo.getOtherPss(i);
+                final int mySwappablePss = memInfo.getOtherSwappablePss(i);
+                final int mySharedDirty = memInfo.getOtherSharedDirty(i);
+                final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
+                final int mySharedClean = memInfo.getOtherSharedClean(i);
+                final int myPrivateClean = memInfo.getOtherPrivateClean(i);
+                final int mySwappedOut = memInfo.getOtherSwappedOut(i);
+                final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
+                if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
+                        || mySharedClean != 0 || myPrivateClean != 0
+                        || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
+                    dumpHeap(proto, MemInfoProto.NativeProcess.OTHER_HEAPS,
+                            Debug.MemoryInfo.getOtherLabel(i),
+                            myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
+                            mySharedClean, myPrivateClean,
+                            memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss);
+
+                    otherPss -= myPss;
+                    otherSwappablePss -= mySwappablePss;
+                    otherSharedDirty -= mySharedDirty;
+                    otherPrivateDirty -= myPrivateDirty;
+                    otherSharedClean -= mySharedClean;
+                    otherPrivateClean -= myPrivateClean;
+                    otherSwappedOut -= mySwappedOut;
+                    otherSwappedOutPss -= mySwappedOutPss;
+                }
+            }
+
+            dumpHeap(proto, MemInfoProto.NativeProcess.UNKNOWN_HEAP, "Unknown",
+                    otherPss, otherSwappablePss,
+                    otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
+                    memInfo.hasSwappedOutPss, otherSwappedOut, otherSwappedOutPss);
+            final long tToken = proto.start(MemInfoProto.NativeProcess.TOTAL_HEAP);
+            dumpHeap(proto, MemInfoProto.NativeProcess.HeapInfo.MEM_INFO, "TOTAL",
+                    memInfo.getTotalPss(), memInfo.getTotalSwappablePss(),
+                    memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
+                    memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
+                    memInfo.hasSwappedOutPss, memInfo.getTotalSwappedOut(),
+                    memInfo.getTotalSwappedOutPss());
+            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_SIZE_KB, nativeMax + dalvikMax);
+            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_ALLOC_KB,
+                    nativeAllocated + dalvikAllocated);
+            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_FREE_KB, nativeFree + dalvikFree);
+            proto.end(tToken);
+
+            if (dumpDalvik) {
+                for (int i = Debug.MemoryInfo.NUM_OTHER_STATS;
+                        i < Debug.MemoryInfo.NUM_OTHER_STATS + Debug.MemoryInfo.NUM_DVK_STATS;
+                        i++) {
+                    final int myPss = memInfo.getOtherPss(i);
+                    final int mySwappablePss = memInfo.getOtherSwappablePss(i);
+                    final int mySharedDirty = memInfo.getOtherSharedDirty(i);
+                    final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
+                    final int mySharedClean = memInfo.getOtherSharedClean(i);
+                    final int myPrivateClean = memInfo.getOtherPrivateClean(i);
+                    final int mySwappedOut = memInfo.getOtherSwappedOut(i);
+                    final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
+                    if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
+                            || mySharedClean != 0 || myPrivateClean != 0
+                            || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
+                        dumpHeap(proto, MemInfoProto.NativeProcess.DALVIK_DETAILS,
+                                Debug.MemoryInfo.getOtherLabel(i),
+                                myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
+                                mySharedClean, myPrivateClean,
+                                memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss);
+                    }
+                }
+            }
+        }
+
+        final long asToken = proto.start(MemInfoProto.NativeProcess.APP_SUMMARY);
+        proto.write(MemInfoProto.NativeProcess.AppSummary.JAVA_HEAP_PSS_KB,
+                memInfo.getSummaryJavaHeap());
+        proto.write(MemInfoProto.NativeProcess.AppSummary.NATIVE_HEAP_PSS_KB,
+                memInfo.getSummaryNativeHeap());
+        proto.write(MemInfoProto.NativeProcess.AppSummary.CODE_PSS_KB, memInfo.getSummaryCode());
+        proto.write(MemInfoProto.NativeProcess.AppSummary.STACK_PSS_KB, memInfo.getSummaryStack());
+        proto.write(MemInfoProto.NativeProcess.AppSummary.GRAPHICS_PSS_KB,
+                memInfo.getSummaryGraphics());
+        proto.write(MemInfoProto.NativeProcess.AppSummary.PRIVATE_OTHER_PSS_KB,
+                memInfo.getSummaryPrivateOther());
+        proto.write(MemInfoProto.NativeProcess.AppSummary.SYSTEM_PSS_KB,
+                memInfo.getSummarySystem());
+        if (memInfo.hasSwappedOutPss) {
+            proto.write(MemInfoProto.NativeProcess.AppSummary.TOTAL_SWAP_PSS,
+                    memInfo.getSummaryTotalSwapPss());
+        } else {
+            proto.write(MemInfoProto.NativeProcess.AppSummary.TOTAL_SWAP_PSS,
+                    memInfo.getSummaryTotalSwap());
+        }
+        proto.end(asToken);
+    }
+
     public void registerOnActivityPausedListener(Activity activity,
             OnActivityPausedListener listener) {
         synchronized (mOnPauseListeners) {
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index eef2f98..05f6c2a 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -101,4 +101,18 @@
      * not enforced by the profile/device owner.
      */
     public abstract Intent createUserRestrictionSupportIntent(int userId, String userRestriction);
+
+    /**
+     * Returns whether this user/profile is affiliated with the device.
+     *
+     * <p>
+     * By definition, the user that the device owner runs on is always affiliated with the device.
+     * Any other user/profile is considered affiliated with the device if the set specified by its
+     * profile owner via {@link DevicePolicyManager#setAffiliationIds} intersects with the device
+     * owner's.
+     * <p>
+     * Profile owner on the primary user will never be considered as affiliated as there is no
+     * device owner to be affiliated with.
+     */
+    public abstract boolean isUserAffiliatedWithDevice(int userId);
 }
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 02c7bd6..062dcce 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -117,8 +117,14 @@
     public static final String SERIAL = getString("no.such.thing");
 
     /**
-     * Gets the hardware serial, if available.
-     * @return The serial if specified.
+     * Gets the hardware serial number, if available.
+     *
+     * <p class="note"><b>Note:</b> Root access may allow you to modify device identifiers, such as
+     * the hardware serial number. If you change these identifiers, you can use
+     * <a href="/training/articles/security-key-attestation.html">key attestation</a> to obtain
+     * proof of the device's original identifiers.
+     *
+     * @return The serial number if specified.
      */
     @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
     public static String getSerial() {
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index f903012..2169457 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -158,7 +158,6 @@
      * <p>
      * Dismiss all currently expired timers. If there are no expired timers, then this is a no-op.
      * </p>
-     * @hide
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_DISMISS_TIMER = "android.intent.action.DISMISS_TIMER";
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index ecdabcf..73a9fbb 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -164,4 +164,9 @@
         (section).type = SECTION_DUMPSYS,
         (section).args = "window --proto"
     ];
+
+    optional com.android.server.am.proto.MemInfoProto meminfo = 3018 [
+        (section).type = SECTION_DUMPSYS,
+        (section).args = "meminfo --proto"
+    ];
 }
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 889842c..3af6f51 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -16,16 +16,16 @@
 
 syntax = "proto2";
 
+package com.android.server.am.proto;
+
 import "frameworks/base/core/proto/android/app/notification.proto";
 import "frameworks/base/core/proto/android/content/intent.proto";
-import "frameworks/base/core/proto/android/server/intentresolver.proto";
-import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
 import "frameworks/base/core/proto/android/graphics/rect.proto";
 import "frameworks/base/core/proto/android/os/looper.proto";
+import "frameworks/base/core/proto/android/server/intentresolver.proto";
+import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
 import "frameworks/base/core/proto/android/util/common.proto";
 
-package com.android.server.am.proto;
-
 option java_multiple_files = true;
 
 message ActivityManagerServiceProto {
@@ -159,6 +159,69 @@
   repeated BroadcastSummary historical_broadcasts_summary = 6;
 }
 
+message MemInfoProto {
+  optional int64 uptime_duration_ms = 1;
+  optional int64 elapsed_realtime_ms = 2;
+
+  message NativeProcess {
+    optional int32 pid = 1;
+    optional string process_name = 2;
+
+    message MemoryInfo {
+      optional string name = 1;
+      // The proportional set size for the heap.
+      optional int32 total_pss_kb = 2;
+      // The proportional set size that is swappable for the heap.
+      optional int32 clean_pss_kb = 3;
+      // The private dirty pages used by the heap.
+      optional int32 shared_dirty_kb = 4;
+      // The shared dirty pages used by the heap.
+      optional int32 private_dirty_kb = 5;
+      // The shared clean pages used by the heap.
+      optional int32 shared_clean_kb = 6;
+      // The private clean pages used by the heap.
+      optional int32 private_clean_kb = 7;
+      oneof dirty_swap {
+        // The dirty the pages that have been swapped out.
+        int32 dirty_swap_kb = 8;
+        // The dirty the pages that have been swapped out, proportional.
+        int32 dirty_swap_pss_kb = 9;
+      }
+    }
+    message HeapInfo {
+      optional MemoryInfo mem_info = 1;
+      optional int32 heap_size_kb = 2;
+      optional int32 heap_alloc_kb = 3;
+      optional int32 heap_free_kb = 4;
+    }
+    optional HeapInfo native_heap = 3;
+    optional HeapInfo dalvik_heap = 4;
+    repeated MemoryInfo other_heaps = 5;
+    optional HeapInfo unknown_heap = 6;
+    // Summation of native_heap, dalvik_heap, and other_heaps.
+    optional HeapInfo total_heap = 7;
+
+    repeated MemoryInfo dalvik_details = 8;
+
+    message AppSummary {
+      optional int32 java_heap_pss_kb = 1;
+      optional int32 native_heap_pss_kb = 2;
+      optional int32 code_pss_kb = 3;
+      optional int32 stack_pss_kb = 4;
+      optional int32 graphics_pss_kb = 5;
+      optional int32 private_other_pss_kb = 6;
+      optional int32 system_pss_kb = 7;
+
+      oneof total_swap {
+        int32 total_swap_pss = 8;
+        int32 total_swap_kb = 9;
+      }
+    }
+    optional AppSummary app_summary = 9;
+  }
+  repeated NativeProcess native_processes = 3;
+}
+
 message StickyBroadcastProto {
   optional int32 user = 1;
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 171f74f..5f756fa 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3169,6 +3169,10 @@
          classes are instantiated in the order of the array. -->
     <string-array translatable="false" name="config_deviceSpecificSystemServices"></string-array>
 
+    <!-- Class name of the device specific implementation to replace the DevicePolicyManagerService
+         or empty if the default should be used. -->
+    <string translatable="false" name="config_deviceSpecificDevicePolicyManagerService"></string>
+
     <!-- Component name of media projection permission dialog -->
     <string name="config_mediaProjectionPermissionDialogComponent" translateable="false">com.android.systemui/com.android.systemui.media.MediaProjectionPermissionActivity</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a115816..ad947b7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -459,6 +459,7 @@
   <java-symbol type="bool" name="config_hasPermanentDpad" />
   <java-symbol type="bool" name="config_useDefaultFocusHighlight" />
   <java-symbol type="array" name="config_deviceSpecificSystemServices" />
+  <java-symbol type="string" name="config_deviceSpecificDevicePolicyManagerService" />
 
   <java-symbol type="color" name="tab_indicator_text_v4" />
 
diff --git a/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java b/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java
index 5f6f62a..978ea7a 100644
--- a/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java
@@ -45,8 +45,9 @@
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 abstract class AbstractCrossUserContentResolverTest {
-    private final static int TIMEOUT_SERVICE_CONNECTION_SEC = 4;
-    private final static int TIMEOUT_CONTENT_CHANGE_SEC = 4;
+    private static final int TIMEOUT_SERVICE_CONNECTION_SEC = 4;
+    private static final int TIMEOUT_CONTENT_CHANGE_SEC = 4;
+    private static final int TIMEOUT_USER_UNLOCK_SEC = 4;
 
     private Context mContext;
     protected UserManager mUm;
@@ -61,7 +62,7 @@
         mCrossUserId = userInfo.id;
         final PackageManager pm = mContext.getPackageManager();
         pm.installExistingPackageAsUser(mContext.getPackageName(), mCrossUserId);
-        ActivityManager.getService().startUserInBackground(mCrossUserId);
+        unlockUser();
 
         final CountDownLatch connectionLatch = new CountDownLatch(1);
         mServiceConnection = new CrossUserContentServiceConnection(connectionLatch);
@@ -77,6 +78,30 @@
 
     protected abstract UserInfo createUser() throws RemoteException ;
 
+    private void unlockUser() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        final BroadcastReceiver receiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL)
+                        == mCrossUserId) {
+                    latch.countDown();
+                }
+            }
+        };
+        mContext.registerReceiverAsUser(receiver, UserHandle.of(mCrossUserId),
+                new IntentFilter(Intent.ACTION_USER_UNLOCKED), null, null);
+        ActivityManager.getService().startUserInBackground(mCrossUserId);
+
+        try {
+            if (!latch.await(TIMEOUT_USER_UNLOCK_SEC, TimeUnit.SECONDS)) {
+                fail("Timed out waiting for the u" + mCrossUserId + " to unlock");
+            }
+        } finally {
+            mContext.unregisterReceiver(receiver);
+        }
+    }
+
     @After
     public void tearDown() throws Exception {
         if (mCrossUserId != -1) {
diff --git a/core/tests/overlaytests/OverlayAppFiltered/Android.mk b/core/tests/overlaytests/OverlayAppFiltered/Android.mk
index 8ba21df..f76de7a 100644
--- a/core/tests/overlaytests/OverlayAppFiltered/Android.mk
+++ b/core/tests/overlaytests/OverlayAppFiltered/Android.mk
@@ -3,8 +3,6 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES += legacy-test
-
 LOCAL_SDK_VERSION := system_current
 
 LOCAL_PACKAGE_NAME := com.android.overlaytest.filtered_app_overlay
diff --git a/core/tests/overlaytests/OverlayAppFirst/Android.mk b/core/tests/overlaytests/OverlayAppFirst/Android.mk
index 51f4487..bf9416c 100644
--- a/core/tests/overlaytests/OverlayAppFirst/Android.mk
+++ b/core/tests/overlaytests/OverlayAppFirst/Android.mk
@@ -3,8 +3,6 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES += legacy-test
-
 LOCAL_SDK_VERSION := current
 
 LOCAL_PACKAGE_NAME := com.android.overlaytest.first_app_overlay
diff --git a/core/tests/overlaytests/OverlayAppSecond/Android.mk b/core/tests/overlaytests/OverlayAppSecond/Android.mk
index b3cfd18..bb7d142 100644
--- a/core/tests/overlaytests/OverlayAppSecond/Android.mk
+++ b/core/tests/overlaytests/OverlayAppSecond/Android.mk
@@ -3,8 +3,6 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES += legacy-test
-
 LOCAL_SDK_VERSION := current
 
 LOCAL_PACKAGE_NAME := com.android.overlaytest.second_app_overlay
diff --git a/core/tests/overlaytests/OverlayTest/Android.mk b/core/tests/overlaytests/OverlayTest/Android.mk
index 964348f..5fe7b91 100644
--- a/core/tests/overlaytests/OverlayTest/Android.mk
+++ b/core/tests/overlaytests/OverlayTest/Android.mk
@@ -7,7 +7,7 @@
 
 LOCAL_DEX_PREOPT := false
 
-LOCAL_JAVA_LIBRARIES += legacy-test
+LOCAL_JAVA_LIBRARIES += android.test.base
 
 LOCAL_MODULE_PATH := $(TARGET_OUT)/app
 
diff --git a/core/tests/overlaytests/OverlayTestOverlay/Android.mk b/core/tests/overlaytests/OverlayTestOverlay/Android.mk
index 5265d91..ed33046 100644
--- a/core/tests/overlaytests/OverlayTestOverlay/Android.mk
+++ b/core/tests/overlaytests/OverlayTestOverlay/Android.mk
@@ -3,8 +3,6 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES += legacy-test
-
 LOCAL_SDK_VERSION := current
 
 LOCAL_PACKAGE_NAME := com.android.overlaytest.overlay
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 5c577ae..96e4fcf 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -417,3 +417,15 @@
         "tests/microbench/TaskManagerBench.cpp",
     ],
 }
+
+// ----------------------------------------
+// Phony target to build benchmarks for PGO
+// ----------------------------------------
+
+phony {
+    name: "pgo-targets-hwui",
+    required: [
+        "hwuimicro",
+        "hwuimacro",
+    ]
+}
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 7afe267..e0289f0 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -741,7 +741,7 @@
         /**
          * @hide
          * Same as {@link #setCapturePreset(int)} but authorizes the use of HOTWORD,
-         * REMOTE_SUBMIX and RADIO_TUNER.
+         * REMOTE_SUBMIX, RADIO_TUNER, VOICE_DOWNLINK, VOICE_UPLINK and VOICE_CALL.
          * @param preset
          * @return the same Builder instance.
          */
@@ -749,7 +749,10 @@
         public Builder setInternalCapturePreset(int preset) {
             if ((preset == MediaRecorder.AudioSource.HOTWORD)
                     || (preset == MediaRecorder.AudioSource.REMOTE_SUBMIX)
-                    || (preset == MediaRecorder.AudioSource.RADIO_TUNER)) {
+                    || (preset == MediaRecorder.AudioSource.RADIO_TUNER)
+                    || (preset == MediaRecorder.AudioSource.VOICE_DOWNLINK)
+                    || (preset == MediaRecorder.AudioSource.VOICE_UPLINK)
+                    || (preset == MediaRecorder.AudioSource.VOICE_CALL)) {
                 mSource = preset;
             } else {
                 setCapturePreset(preset);
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 0906ba5..27784e9 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -1516,66 +1516,13 @@
     }
 
     /**
-     * Helper class to handle the forwarding of native events to the appropriate listener
-     * (potentially) handled in a different thread
-     */
-    private class NativeRoutingEventHandlerDelegate {
-        private final Handler mHandler;
-
-        NativeRoutingEventHandlerDelegate(final AudioRecord record,
-                                   final AudioRouting.OnRoutingChangedListener listener,
-                                   Handler handler) {
-            // find the looper for our new event handler
-            Looper looper;
-            if (handler != null) {
-                looper = handler.getLooper();
-            } else {
-                // no given handler, use the looper the AudioRecord was created in
-                looper = mInitializationLooper;
-            }
-
-            // construct the event handler with this looper
-            if (looper != null) {
-                // implement the event handler delegate
-                mHandler = new Handler(looper) {
-                    @Override
-                    public void handleMessage(Message msg) {
-                        if (record == null) {
-                            return;
-                        }
-                        switch(msg.what) {
-                        case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
-                            if (listener != null) {
-                                listener.onRoutingChanged(record);
-                            }
-                            break;
-                        default:
-                            loge("Unknown native event type: " + msg.what);
-                            break;
-                        }
-                    }
-                };
-            } else {
-                mHandler = null;
-            }
-        }
-
-        Handler getHandler() {
-            return mHandler;
-        }
-    }
-
-    /**
      * Sends device list change notification to all listeners.
      */
     private void broadcastRoutingChange() {
         AudioManager.resetAudioPortGeneration();
         synchronized (mRoutingChangeListeners) {
             for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) {
-                Handler handler = delegate.getHandler();
-                if (handler != null) {
-                    handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
-                }
+                delegate.notifyClient();
             }
         }
     }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 50145f8..e535fdf 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -2856,10 +2856,7 @@
         AudioManager.resetAudioPortGeneration();
         synchronized (mRoutingChangeListeners) {
             for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) {
-                Handler handler = delegate.getHandler();
-                if (handler != null) {
-                    handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
-                }
+                delegate.notifyClient();
             }
         }
     }
@@ -2943,56 +2940,6 @@
         }
     }
 
-    /**
-     * Helper class to handle the forwarding of native events to the appropriate listener
-     * (potentially) handled in a different thread
-     */
-    private class NativeRoutingEventHandlerDelegate {
-        private final Handler mHandler;
-
-        NativeRoutingEventHandlerDelegate(final AudioTrack track,
-                                   final AudioRouting.OnRoutingChangedListener listener,
-                                   Handler handler) {
-            // find the looper for our new event handler
-            Looper looper;
-            if (handler != null) {
-                looper = handler.getLooper();
-            } else {
-                // no given handler, use the looper the AudioTrack was created in
-                looper = mInitializationLooper;
-            }
-
-            // construct the event handler with this looper
-            if (looper != null) {
-                // implement the event handler delegate
-                mHandler = new Handler(looper) {
-                    @Override
-                    public void handleMessage(Message msg) {
-                        if (track == null) {
-                            return;
-                        }
-                        switch(msg.what) {
-                        case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
-                            if (listener != null) {
-                                listener.onRoutingChanged(track);
-                            }
-                            break;
-                        default:
-                            loge("Unknown native event type: " + msg.what);
-                            break;
-                        }
-                    }
-                };
-            } else {
-                mHandler = null;
-            }
-        }
-
-        Handler getHandler() {
-            return mHandler;
-        }
-    }
-
     //---------------------------------------------------------
     // Methods for IPlayer interface
     //--------------------
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 649c091..1bc3dfa 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1514,7 +1514,8 @@
             if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
                 enableNativeRoutingCallbacksLocked(true);
                 mRoutingChangeListeners.put(
-                        listener, new NativeRoutingEventHandlerDelegate(this, listener, handler));
+                        listener, new NativeRoutingEventHandlerDelegate(this, listener,
+                                handler != null ? handler : mEventHandler));
             }
         }
     }
@@ -1535,36 +1536,6 @@
         }
     }
 
-    /**
-     * Helper class to handle the forwarding of native events to the appropriate listener
-     * (potentially) handled in a different thread
-     */
-    private class NativeRoutingEventHandlerDelegate {
-        private MediaPlayer mMediaPlayer;
-        private AudioRouting.OnRoutingChangedListener mOnRoutingChangedListener;
-        private Handler mHandler;
-
-        NativeRoutingEventHandlerDelegate(final MediaPlayer mediaPlayer,
-                final AudioRouting.OnRoutingChangedListener listener, Handler handler) {
-            mMediaPlayer = mediaPlayer;
-            mOnRoutingChangedListener = listener;
-            mHandler = handler != null ? handler : mEventHandler;
-        }
-
-        void notifyClient() {
-            if (mHandler != null) {
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        if (mOnRoutingChangedListener != null) {
-                            mOnRoutingChangedListener.onRoutingChanged(mMediaPlayer);
-                        }
-                    }
-                });
-            }
-        }
-    }
-
     private native final boolean native_setOutputDevice(int deviceId);
     private native final int native_getRoutedDeviceId();
     private native final void native_enableDeviceCallback(boolean enabled);
diff --git a/media/java/android/media/NativeRoutingEventHandlerDelegate.java b/media/java/android/media/NativeRoutingEventHandlerDelegate.java
new file mode 100644
index 0000000..9a6baf1
--- /dev/null
+++ b/media/java/android/media/NativeRoutingEventHandlerDelegate.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 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.media;
+
+import android.os.Handler;
+
+/**
+ * Helper class {@link AudioTrack}, {@link AudioRecord}, {@link MediaPlayer} and {@link MediaRecorder}
+ * to handle the forwarding of native events to the appropriate listener
+ * (potentially) handled in a different thread.
+ * @hide
+ */
+class NativeRoutingEventHandlerDelegate {
+    private AudioRouting mAudioRouting;
+    private AudioRouting.OnRoutingChangedListener mOnRoutingChangedListener;
+    private Handler mHandler;
+
+    NativeRoutingEventHandlerDelegate(final AudioRouting audioRouting,
+            final AudioRouting.OnRoutingChangedListener listener, Handler handler) {
+        mAudioRouting = audioRouting;
+        mOnRoutingChangedListener = listener;
+        mHandler = handler;
+    }
+
+    void notifyClient() {
+        if (mHandler != null) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    if (mOnRoutingChangedListener != null) {
+                        mOnRoutingChangedListener.onRoutingChanged(mAudioRouting);
+                    }
+                }
+            });
+        }
+    }
+}
diff --git a/media/mca/filterfw/Android.mk b/media/mca/filterfw/Android.mk
index 334f4e2..37f1e13 100644
--- a/media/mca/filterfw/Android.mk
+++ b/media/mca/filterfw/Android.mk
@@ -26,6 +26,8 @@
 
 LOCAL_MODULE := libfilterfw
 
+LOCAL_CFLAGS := -Wall -Werror
+
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_WHOLE_STATIC_LIBRARIES := libfilterfw_jni \
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index bfaa8cd..c91cdfc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -256,6 +256,9 @@
             }
             case MotionEvent.ACTION_MOVE: {
                 int activePointerIndex = ev.findPointerIndex(mActivePointerId);
+                if (activePointerIndex == -1) {
+                    break;
+                }
                 int y = (int) ev.getY(activePointerIndex);
                 int x = (int) ev.getX(activePointerIndex);
                 if (!mIsScrolling) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index dfd4c17..3a36776 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -629,6 +629,11 @@
             }
         }
 
+        // TODO factor mLightBarController out of this class
+        if (scrim == mScrimBehind) {
+            mLightBarController.setScrimAlpha(alpha);
+        }
+
         final ScrimView scrimView = scrim instanceof  ScrimView ? (ScrimView) scrim : null;
         final boolean wantsAlphaUpdate = alpha != currentAlpha && alpha != animEndValue;
         final boolean wantsTintUpdate = scrimView != null
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index fe992da..e6d7047 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -417,6 +417,7 @@
 import com.android.server.am.proto.ActivityManagerServiceProto;
 import com.android.server.am.proto.BroadcastProto;
 import com.android.server.am.proto.GrantUriProto;
+import com.android.server.am.proto.MemInfoProto;
 import com.android.server.am.proto.NeededUriGrantsProto;
 import com.android.server.am.proto.StickyBroadcastProto;
 import com.android.server.firewall.IntentFirewall;
@@ -2569,14 +2570,13 @@
             @Override
             public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args,
                     boolean asProto) {
-                if (asProto) return;
-                mActivityManagerService.dumpApplicationMemoryUsage(fd,
-                        pw, "  ", new String[] {"-a"}, false, null);
+                dump(fd, pw, new String[] {"-a"}, asProto);
             }
+
             @Override
             public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
-                if (asProto) return;
-                mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args, false, null);
+                mActivityManagerService.dumpApplicationMemoryUsage(
+                        fd, pw, "  ", args, false, null, asProto);
             }
         };
 
@@ -17207,8 +17207,8 @@
         boolean dumpProto;
     }
 
-    final void dumpApplicationMemoryUsage(FileDescriptor fd,
-            PrintWriter pw, String prefix, String[] args, boolean brief, PrintWriter categoryPw) {
+    final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw, String prefix,
+            String[] args, boolean brief, PrintWriter categoryPw, boolean asProto) {
         MemoryUsageDumpOptions opts = new MemoryUsageDumpOptions();
         opts.dumpDetails = false;
         opts.dumpFullDetails = false;
@@ -17221,7 +17221,7 @@
         opts.packages = false;
         opts.isCheckinRequest = false;
         opts.dumpSwapPss = false;
-        opts.dumpProto = false;
+        opts.dumpProto = asProto;
 
         int opti = 0;
         while (opti < args.length) {
@@ -17289,7 +17289,7 @@
         }
     }
 
-    final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw, String prefix,
+    private final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw, String prefix,
             MemoryUsageDumpOptions opts, String[] innerArgs, boolean brief,
             ArrayList<ProcessRecord> procs, PrintWriter categoryPw) {
         long uptime = SystemClock.uptimeMillis();
@@ -17298,54 +17298,59 @@
 
         if (procs == null) {
             // No Java processes.  Maybe they want to print a native process.
-            if (innerArgs.length > 0 && innerArgs[0].charAt(0) != '-') {
-                ArrayList<ProcessCpuTracker.Stats> nativeProcs
-                        = new ArrayList<ProcessCpuTracker.Stats>();
-                updateCpuStatsNow();
-                int findPid = -1;
-                try {
-                    findPid = Integer.parseInt(innerArgs[0]);
-                } catch (NumberFormatException e) {
-                }
-                synchronized (mProcessCpuTracker) {
-                    final int N = mProcessCpuTracker.countStats();
-                    for (int i=0; i<N; i++) {
-                        ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
-                        if (st.pid == findPid || (st.baseName != null
-                                && st.baseName.equals(innerArgs[0]))) {
-                            nativeProcs.add(st);
+            String proc = "N/A";
+            if (innerArgs.length > 0) {
+                proc = innerArgs[0];
+                if (proc.charAt(0) != '-') {
+                    ArrayList<ProcessCpuTracker.Stats> nativeProcs
+                            = new ArrayList<ProcessCpuTracker.Stats>();
+                    updateCpuStatsNow();
+                    int findPid = -1;
+                    try {
+                        findPid = Integer.parseInt(innerArgs[0]);
+                    } catch (NumberFormatException e) {
+                    }
+                    synchronized (mProcessCpuTracker) {
+                        final int N = mProcessCpuTracker.countStats();
+                        for (int i=0; i<N; i++) {
+                            ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
+                            if (st.pid == findPid || (st.baseName != null
+                                    && st.baseName.equals(innerArgs[0]))) {
+                                nativeProcs.add(st);
+                            }
                         }
                     }
-                }
-                if (nativeProcs.size() > 0) {
-                    dumpApplicationMemoryUsageHeader(pw, uptime, realtime, opts.isCheckinRequest,
-                            opts.isCompact);
-                    Debug.MemoryInfo mi = null;
-                    for (int i = nativeProcs.size() - 1 ; i >= 0 ; i--) {
-                        final ProcessCpuTracker.Stats r = nativeProcs.get(i);
-                        final int pid = r.pid;
-                        if (!opts.isCheckinRequest && opts.dumpDetails) {
-                            pw.println("\n** MEMINFO in pid " + pid + " [" + r.baseName + "] **");
+                    if (nativeProcs.size() > 0) {
+                        dumpApplicationMemoryUsageHeader(pw, uptime, realtime,
+                                opts.isCheckinRequest, opts.isCompact);
+                        Debug.MemoryInfo mi = null;
+                        for (int i = nativeProcs.size() - 1 ; i >= 0 ; i--) {
+                            final ProcessCpuTracker.Stats r = nativeProcs.get(i);
+                            final int pid = r.pid;
+                            if (!opts.isCheckinRequest && opts.dumpDetails) {
+                                pw.println("\n** MEMINFO in pid " + pid + " [" + r.baseName + "] **");
+                            }
+                            if (mi == null) {
+                                mi = new Debug.MemoryInfo();
+                            }
+                            if (opts.dumpDetails || (!brief && !opts.oomOnly)) {
+                                Debug.getMemoryInfo(pid, mi);
+                            } else {
+                                mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null);
+                                mi.dalvikPrivateDirty = (int)tmpLong[0];
+                            }
+                            ActivityThread.dumpMemInfoTable(pw, mi, opts.isCheckinRequest,
+                                    opts.dumpFullDetails, opts.dumpDalvik, opts.dumpSummaryOnly,
+                                    pid, r.baseName, 0, 0, 0, 0, 0, 0);
+                            if (opts.isCheckinRequest) {
+                                pw.println();
+                            }
                         }
-                        if (mi == null) {
-                            mi = new Debug.MemoryInfo();
-                        }
-                        if (opts.dumpDetails || (!brief && !opts.oomOnly)) {
-                            Debug.getMemoryInfo(pid, mi);
-                        } else {
-                            mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null);
-                            mi.dalvikPrivateDirty = (int)tmpLong[0];
-                        }
-                        ActivityThread.dumpMemInfoTable(pw, mi, opts.isCheckinRequest, opts.dumpFullDetails,
-                                opts.dumpDalvik, opts.dumpSummaryOnly, pid, r.baseName, 0, 0, 0, 0, 0, 0);
-                        if (opts.isCheckinRequest) {
-                            pw.println();
-                        }
+                        return;
                     }
-                    return;
                 }
             }
-            pw.println("No process found for: " + innerArgs[0]);
+            pw.println("No process found for: " + proc);
             return;
         }
 
@@ -17768,15 +17773,77 @@
         }
     }
 
-    final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw,
+    private final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw,
             MemoryUsageDumpOptions opts, String[] innerArgs, boolean brief,
             ArrayList<ProcessRecord> procs) {
-        ProtoOutputStream proto = new ProtoOutputStream(fd);
+        final long uptimeMs = SystemClock.uptimeMillis();
+        final long realtimeMs = SystemClock.elapsedRealtime();
+        final long[] tmpLong = new long[1];
 
-        // TODO: implement
-        pw.println("Not yet implemented. Have a cookie instead! :]");
+        if (procs == null) {
+            // No Java processes.  Maybe they want to print a native process.
+            String proc = "N/A";
+            if (innerArgs.length > 0) {
+                proc = innerArgs[0];
+                if (proc.charAt(0) != '-') {
+                    ArrayList<ProcessCpuTracker.Stats> nativeProcs
+                            = new ArrayList<ProcessCpuTracker.Stats>();
+                    updateCpuStatsNow();
+                    int findPid = -1;
+                    try {
+                        findPid = Integer.parseInt(innerArgs[0]);
+                    } catch (NumberFormatException e) {
+                    }
+                    synchronized (mProcessCpuTracker) {
+                        final int N = mProcessCpuTracker.countStats();
+                        for (int i=0; i<N; i++) {
+                            ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
+                            if (st.pid == findPid || (st.baseName != null
+                                    && st.baseName.equals(innerArgs[0]))) {
+                                nativeProcs.add(st);
+                            }
+                        }
+                    }
+                    if (nativeProcs.size() > 0) {
+                        ProtoOutputStream proto = new ProtoOutputStream(fd);
 
-        proto.flush();
+                        proto.write(MemInfoProto.UPTIME_DURATION_MS, uptimeMs);
+                        proto.write(MemInfoProto.ELAPSED_REALTIME_MS, realtimeMs);
+                        Debug.MemoryInfo mi = null;
+                        for (int i = nativeProcs.size() - 1 ; i >= 0 ; i--) {
+                            final ProcessCpuTracker.Stats r = nativeProcs.get(i);
+                            final int pid = r.pid;
+                            final long nToken = proto.start(MemInfoProto.NATIVE_PROCESSES);
+
+                            proto.write(MemInfoProto.NativeProcess.PID, pid);
+                            proto.write(MemInfoProto.NativeProcess.PROCESS_NAME, r.baseName);
+
+                            if (mi == null) {
+                                mi = new Debug.MemoryInfo();
+                            }
+                            if (opts.dumpDetails || (!brief && !opts.oomOnly)) {
+                                Debug.getMemoryInfo(pid, mi);
+                            } else {
+                                mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null);
+                                mi.dalvikPrivateDirty = (int)tmpLong[0];
+                            }
+                            ActivityThread.dumpMemInfoTable(proto, mi, opts.dumpDalvik,
+                                    opts.dumpSummaryOnly, 0, 0, 0, 0, 0, 0);
+
+                            proto.end(nToken);
+                        }
+
+                        proto.flush();
+                        return;
+                    }
+                }
+            }
+            Log.d(TAG, "No process found for: " + innerArgs[0]);
+            return;
+        }
+
+        // TODO: finish
+        pw.println("Java processes aren't implemented yet. Have a coffee instead! :]");
     }
 
     private void appendBasicMemEntry(StringBuilder sb, int oomAdj, int procState, long pss,
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index be9b2f3..14128a7 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -27,7 +27,8 @@
 import android.app.NotificationManager;
 import android.app.PackageDeleteObserver;
 import android.app.PackageInstallObserver;
-import android.app.admin.DevicePolicyManager;
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -704,20 +705,25 @@
             mAppOps.checkPackage(callingUid, callerPackageName);
         }
 
-        // Check whether the caller is device owner, in which case we do it silently.
-        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-        boolean isDeviceOwner = (dpm != null) && dpm.isDeviceOwnerAppOnCallingUser(
-                callerPackageName);
+        // Check whether the caller is device owner or affiliated profile owner, in which case we do
+        // it silently.
+        final int callingUserId = UserHandle.getUserId(callingUid);
+        DevicePolicyManagerInternal dpmi =
+                LocalServices.getService(DevicePolicyManagerInternal.class);
+        final boolean isDeviceOwnerOrAffiliatedProfileOwner =
+                dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
+                        DeviceAdminInfo.USES_POLICY_PROFILE_OWNER)
+                        && dpmi.isUserAffiliatedWithDevice(callingUserId);
 
         final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
-                statusReceiver, versionedPackage.getPackageName(), isDeviceOwner, userId);
+                statusReceiver, versionedPackage.getPackageName(),
+                isDeviceOwnerOrAffiliatedProfileOwner, userId);
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
                     == PackageManager.PERMISSION_GRANTED) {
             // Sweet, call straight through!
             mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
-        } else if (isDeviceOwner) {
-            // Allow the DeviceOwner to silently delete packages
+        } else if (isDeviceOwnerOrAffiliatedProfileOwner) {
+            // Allow the device owner and affiliated profile owner to silently delete packages
             // Need to clear the calling identity to get DELETE_PACKAGES permission
             long ident = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 0e11cc7..711352f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -41,7 +41,8 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.admin.DevicePolicyManager;
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -91,6 +92,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.server.LocalServices;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
 
@@ -311,14 +313,14 @@
     };
 
     /**
-     * @return {@code true} iff the installing is app an device owner?
+     * @return {@code true} iff the installing is app an device owner or affiliated profile owner.
      */
-    private boolean isInstallerDeviceOwnerLocked() {
-        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-
-        return (dpm != null) && dpm.isDeviceOwnerAppOnCallingUser(
-                mInstallerPackageName);
+    private boolean isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked() {
+        DevicePolicyManagerInternal dpmi =
+                LocalServices.getService(DevicePolicyManagerInternal.class);
+        return dpmi != null && dpmi.isActiveAdminWithPolicy(mInstallerUid,
+                DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) && dpmi.isUserAffiliatedWithDevice(
+                userId);
     }
 
     /**
@@ -347,10 +349,10 @@
         final boolean forcePermissionPrompt =
                 (params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0;
 
-        // Device owners are allowed to silently install packages, so the permission check is
-        // waived if the installer is the device owner.
+        // Device owners and affiliated profile owners  are allowed to silently install packages, so
+        // the permission check is waived if the installer is the device owner.
         return forcePermissionPrompt || !(isPermissionGranted || isInstallerRoot
-                || isInstallerDeviceOwnerLocked());
+                || isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked());
     }
 
     public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
@@ -705,7 +707,8 @@
             assertPreparedAndNotDestroyedLocked("commit");
 
             final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(
-                    mContext, statusReceiver, sessionId, isInstallerDeviceOwnerLocked(), userId);
+                    mContext, statusReceiver, sessionId,
+                    isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId);
             mRemoteObserver = adapter.getBinder();
 
             if (forTransfer) {
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index e240ec5..00c208d 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.stats;
 
+import android.annotation.Nullable;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -25,16 +26,22 @@
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.net.NetworkStats;
+import android.net.wifi.IWifiManager;
+import android.net.wifi.WifiActivityEnergyInfo;
+import android.telephony.ModemActivityInfo;
+import android.telephony.TelephonyManager;
 import android.os.BatteryStatsInternal;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.IStatsCompanionService;
 import android.os.IStatsManager;
+import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StatsLogEventWrapper;
+import android.os.SynchronousResultReceiver;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Slog;
@@ -52,6 +59,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeoutException;
 
 /**
  * Helper service for statsd (the native stats management service in cmds/statsd/).
@@ -60,6 +68,13 @@
  * @hide
  */
 public class StatsCompanionService extends IStatsCompanionService.Stub {
+    /**
+     * How long to wait on an individual subsystem to return its stats.
+     */
+    private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
+
+    public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
+
     static final String TAG = "StatsCompanionService";
     static final boolean DEBUG = true;
     public static final String ACTION_TRIGGER_COLLECTION =
@@ -79,6 +94,8 @@
     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
     private final KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
+    private IWifiManager mWifiManager = null;
+    private TelephonyManager mTelephony = null;
 
     public StatsCompanionService(Context context) {
         super();
@@ -389,6 +406,40 @@
         return ret;
     }
 
+    /**
+     * Helper method to extract the Parcelable controller info from a
+     * SynchronousResultReceiver.
+     */
+    private static <T extends Parcelable> T awaitControllerInfo(
+            @Nullable SynchronousResultReceiver receiver) {
+        if (receiver == null) {
+            return null;
+        }
+
+        try {
+            final SynchronousResultReceiver.Result result =
+                    receiver.awaitResult(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS);
+            if (result.bundle != null) {
+                // This is the final destination for the Bundle.
+                result.bundle.setDefusable(true);
+
+                final T data = result.bundle.getParcelable(
+                        RESULT_RECEIVER_CONTROLLER_KEY);
+                if (data != null) {
+                    return data;
+                }
+            }
+            Slog.e(TAG, "no controller energy info supplied for " + receiver.getName());
+        } catch (TimeoutException e) {
+            Slog.w(TAG, "timeout reading " + receiver.getName() + " stats");
+        }
+        return null;
+    }
+
+    /**
+     *
+     * Pulls wifi controller activity energy info from WiFiManager
+     */
     @Override // Binder call
     public StatsLogEventWrapper[] pullData(int tagId) {
         enforceCallingPermission();
@@ -509,6 +560,59 @@
                 }
                 return ret.toArray(new StatsLogEventWrapper[ret.size()]);
             }
+            case StatsLog.WIFI_ACTIVITY_ENERGY_INFO_PULLED: {
+                List<StatsLogEventWrapper> ret = new ArrayList();
+                long token = Binder.clearCallingIdentity();
+                if (mWifiManager == null) {
+                    mWifiManager = IWifiManager.Stub.asInterface(ServiceManager.getService(
+                            Context.WIFI_SERVICE));
+                }
+                if (mWifiManager != null) {
+                    try {
+                        SynchronousResultReceiver wifiReceiver = new SynchronousResultReceiver("wifi");
+                        mWifiManager.requestActivityInfo(wifiReceiver);
+                        final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
+                        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
+                        e.writeLong(wifiInfo.getTimeStamp());
+                        e.writeInt(wifiInfo.getStackState());
+                        e.writeLong(wifiInfo.getControllerTxTimeMillis());
+                        e.writeLong(wifiInfo.getControllerRxTimeMillis());
+                        e.writeLong(wifiInfo.getControllerIdleTimeMillis());
+                        e.writeLong(wifiInfo.getControllerEnergyUsed());
+                        ret.add(e);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Pulling wifiManager for wifi controller activity energy info has error", e);
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+                break;
+            }
+            case StatsLog.MODEM_ACTIVITY_INFO_PULLED: {
+                List<StatsLogEventWrapper> ret = new ArrayList();
+                long token = Binder.clearCallingIdentity();
+                if (mTelephony == null) {
+                    mTelephony = TelephonyManager.from(mContext);
+                }
+                if (mTelephony != null) {
+                    SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
+                    mTelephony.requestModemActivityInfo(modemReceiver);
+                    final ModemActivityInfo modemInfo = awaitControllerInfo(modemReceiver);
+                    StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
+                    e.writeLong(modemInfo.getTimestamp());
+                    e.writeLong(modemInfo.getSleepTimeMillis());
+                    e.writeLong(modemInfo.getIdleTimeMillis());
+                    e.writeLong(modemInfo.getTxTimeMillis()[0]);
+                    e.writeLong(modemInfo.getTxTimeMillis()[1]);
+                    e.writeLong(modemInfo.getTxTimeMillis()[2]);
+                    e.writeLong(modemInfo.getTxTimeMillis()[3]);
+                    e.writeLong(modemInfo.getTxTimeMillis()[4]);
+                    e.writeLong(modemInfo.getRxTimeMillis());
+                    e.writeLong(modemInfo.getEnergyUsed());
+                    ret.add(e);
+                }
+                break;
+            }
             default:
                 Slog.w(TAG, "No such tagId data as " + tagId);
                 return null;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
new file mode 100644
index 0000000..dddff8f
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 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.server.devicepolicy;
+
+import android.app.admin.IDevicePolicyManager;
+
+import com.android.internal.R;
+import com.android.server.SystemService;
+
+/**
+ * Defines the required interface for IDevicePolicyManager implemenation.
+ *
+ * <p>The interface consists of public parts determined by {@link IDevicePolicyManager} and also
+ * several package private methods required by internal infrastructure.
+ *
+ * <p>Whenever adding an AIDL method to {@link IDevicePolicyManager}, an empty override method
+ * should be added here to avoid build breakage in downstream branches.
+ */
+abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
+    /**
+     * To be called by {@link DevicePolicyManagerService#Lifecycle} during the various boot phases.
+     *
+     * @see {@link SystemService#onBootPhase}.
+     */
+    abstract void systemReady(int phase);
+    /**
+     * To be called by {@link DevicePolicyManagerService#Lifecycle} when a new user starts.
+     *
+     * @see {@link SystemService#onStartUser}
+     */
+    abstract void handleStartUser(int userId);
+    /**
+     * To be called by {@link DevicePolicyManagerService#Lifecycle} when a user is being unlocked.
+     *
+     * @see {@link SystemService#onUnlockUser}
+     */
+    abstract void handleUnlockUser(int userId);
+    /**
+     * To be called by {@link DevicePolicyManagerService#Lifecycle} when a user is being stopped.
+     *
+     * @see {@link SystemService#onStopUser}
+     */
+    abstract void handleStopUser(int userId);
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 60c36d1..d7e4a62 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -198,6 +198,8 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.IllegalStateException;
+import java.lang.reflect.Constructor;
 import java.nio.charset.StandardCharsets;
 import java.text.DateFormat;
 import java.util.ArrayList;
@@ -214,7 +216,7 @@
 /**
  * Implementation of the device policy APIs.
  */
-public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
 
     protected static final String LOG_TAG = "DevicePolicyManager";
 
@@ -451,11 +453,24 @@
     };
 
     public static final class Lifecycle extends SystemService {
-        private DevicePolicyManagerService mService;
+        private BaseIDevicePolicyManager mService;
 
         public Lifecycle(Context context) {
             super(context);
-            mService = new DevicePolicyManagerService(context);
+            String dpmsClassName = context.getResources()
+                    .getString(R.string.config_deviceSpecificDevicePolicyManagerService);
+            if (TextUtils.isEmpty(dpmsClassName)) {
+                dpmsClassName = DevicePolicyManagerService.class.getName();
+            }
+            try {
+                Class serviceClass = Class.forName(dpmsClassName);
+                Constructor constructor = serviceClass.getConstructor(Context.class);
+                mService = (BaseIDevicePolicyManager) constructor.newInstance(context);
+            } catch (Exception e) {
+                throw new IllegalStateException(
+                    "Failed to instantiate DevicePolicyManagerService with class name: "
+                    + dpmsClassName, e);
+            }
         }
 
         @Override
@@ -1551,6 +1566,10 @@
             mContext = context;
         }
 
+        public boolean hasFeature() {
+            return getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
+        }
+
         Context createContextAsUser(UserHandle user) throws PackageManager.NameNotFoundException {
             final String packageName = mContext.getPackageName();
             return mContext.createPackageContextAsUser(packageName, 0, user);
@@ -1848,8 +1867,7 @@
         // TODO: why does SecurityLogMonitor need to be created even when mHasFeature == false?
         mSecurityLogMonitor = new SecurityLogMonitor(this);
 
-        mHasFeature = mInjector.getPackageManager()
-                .hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
+        mHasFeature = mInjector.hasFeature();
         mIsWatch = mInjector.getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_WATCH);
         mBackgroundHandler = BackgroundThread.getHandler();
@@ -3033,6 +3051,7 @@
     }
 
     @VisibleForTesting
+    @Override
     void systemReady(int phase) {
         if (!mHasFeature) {
             return;
@@ -3099,6 +3118,7 @@
         }
     }
 
+    @Override
     void handleStartUser(int userId) {
         updateScreenCaptureDisabledInWindowManager(userId,
                 getScreenCaptureDisabled(null, userId));
@@ -3107,10 +3127,12 @@
         startOwnerService(userId, "start-user");
     }
 
+    @Override
     void handleUnlockUser(int userId) {
         startOwnerService(userId, "unlock-user");
     }
 
+    @Override
     void handleStopUser(int userId) {
         stopOwnerService(userId, "stop-user");
     }
@@ -6943,8 +6965,13 @@
             return;
         }
 
+        final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (this) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            if (!isUserAffiliatedWithDeviceLocked(userId)) {
+                throw new SecurityException("Admin " + who +
+                        " is neither the device owner or affiliated user's profile owner.");
+            }
             long token = mInjector.binderClearCallingIdentity();
             try {
                 mLockPatternUtils.setDeviceOwnerInfo(info != null ? info.toString() : null);
@@ -9236,10 +9263,14 @@
     @Override
     public boolean setKeyguardDisabled(ComponentName who, boolean disabled) {
         Preconditions.checkNotNull(who, "ComponentName is null");
+        final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (this) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            if (!isUserAffiliatedWithDeviceLocked(userId)) {
+                throw new SecurityException("Admin " + who +
+                        " is neither the device owner or affiliated user's profile owner.");
+            }
         }
-        final int userId = UserHandle.getCallingUserId();
 
         long ident = mInjector.binderClearCallingIdentity();
         try {
@@ -9261,7 +9292,11 @@
     public boolean setStatusBarDisabled(ComponentName who, boolean disabled) {
         int userId = UserHandle.getCallingUserId();
         synchronized (this) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            if (!isUserAffiliatedWithDeviceLocked(userId)) {
+                throw new SecurityException("Admin " + who +
+                        " is neither the device owner or affiliated user's profile owner.");
+            }
             DevicePolicyData policy = getUserData(userId);
             if (policy.mStatusBarDisabled != disabled) {
                 boolean isLockTaskMode = false;
@@ -9526,6 +9561,11 @@
             }
             return null;
         }
+
+        @Override
+        public boolean isUserAffiliatedWithDevice(int userId) {
+            return DevicePolicyManagerService.this.isUserAffiliatedWithDeviceLocked(userId);
+        }
     }
 
     private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 062858d..ca4a210 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -188,6 +188,11 @@
     }
 
     /**
+     * Called when the feature is ready to use.
+     */
+    public abstract void onFeatureReady();
+
+    /**
      * Called when the feature is being removed and must be cleaned up.
      */
     public abstract void onFeatureRemoved();
diff --git a/telephony/java/android/telephony/ims/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
index e790d14..4e095e3a 100644
--- a/telephony/java/android/telephony/ims/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
@@ -346,6 +346,11 @@
         return null;
     }
 
+    @Override
+    public void onFeatureReady() {
+
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index a82e608..40c5181 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -36,6 +36,11 @@
     }
 
     @Override
+    public void onFeatureReady() {
+
+    }
+
+    @Override
     public void onFeatureRemoved() {
 
     }
diff --git a/telephony/java/android/telephony/ims/feature/SmsFeature.java b/telephony/java/android/telephony/ims/feature/SmsFeature.java
new file mode 100644
index 0000000..c1366db
--- /dev/null
+++ b/telephony/java/android/telephony/ims/feature/SmsFeature.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2017 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.telephony.ims.feature;
+
+import android.annotation.SystemApi;
+import android.os.RemoteException;
+import com.android.ims.internal.IImsSmsFeature;
+import com.android.ims.internal.ISmsListener;
+
+/**
+ * Base implementation of SMS over IMS functionality.
+ *
+ * @hide
+ */
+public class SmsFeature extends ImsFeature {
+  /**
+   * SMS over IMS format is 3gpp.
+   */
+  public static final int IMS_SMS_FORMAT_3GPP = 1;
+
+  /**
+   * SMS over IMS format is 3gpp2.
+   */
+  public static final int IMS_SMS_FORMAT_3GPP2 = 2;
+
+  /**
+   * Message was sent successfully.
+   */
+  public static final int SEND_STATUS_OK = 1;
+
+  /**
+   * IMS provider failed to send the message and platform should not retry falling back to sending
+   * the message using the radio.
+   */
+  public static final int SEND_STATUS_ERROR = 2;
+
+  /**
+   * IMS provider failed to send the message and platform should retry again after setting TP-RD bit
+   * to high.
+   */
+  public static final int SEND_STATUS_ERROR_RETRY = 3;
+
+  /**
+   * IMS provider failed to send the message and platform should retry falling back to sending
+   * the message using the radio.
+   */
+  public static final int SEND_STATUS_ERROR_FALLBACK = 4;
+
+  /**
+   * Message was delivered successfully.
+   */
+  public static final int DELIVER_STATUS_OK = 1;
+
+  /**
+   * Message was not delivered.
+   */
+  public static final int DELIVER_STATUS_ERROR = 2;
+
+  // Lock for feature synchronization
+  private final Object mLock = new Object();
+  private ISmsListener mSmsListener;
+
+  private final IImsSmsFeature mIImsSmsBinder = new IImsSmsFeature.Stub() {
+    @Override
+    public void registerSmsListener(ISmsListener listener) {
+      synchronized (mLock) {
+        SmsFeature.this.registerSmsListener(listener);
+      }
+    }
+
+    @Override
+    public void sendSms(int format, int messageRef, boolean retry, byte[] pdu) {
+      synchronized (mLock) {
+        SmsFeature.this.sendSms(format, messageRef, retry, pdu);
+      }
+    }
+
+    @Override
+    public void acknowledgeSms(int messageRef, int result) {
+      synchronized (mLock) {
+        SmsFeature.this.acknowledgeSms(messageRef, result);
+      }
+    }
+
+    @Override
+    public int getSmsFormat() {
+      synchronized (mLock) {
+        return SmsFeature.this.getSmsFormat();
+      }
+    }
+  };
+
+  /**
+   * Registers a listener responsible for handling tasks like delivering messages.
+
+   * @param listener listener to register.
+   *
+   * @hide
+   */
+  @SystemApi
+  public final void registerSmsListener(ISmsListener listener) {
+    synchronized (mLock) {
+      mSmsListener = listener;
+    }
+  }
+
+  /**
+   * This method will be triggered by the platform when the user attempts to send an SMS. This
+   * method should be implemented by the IMS providers to provide implementation of sending an SMS
+   * over IMS.
+   *
+   * @param format the format of the message. One of {@link #IMS_SMS_FORMAT_3GPP} or
+   *                {@link #IMS_SMS_FORMAT_3GPP2}
+   * @param messageRef the message reference.
+   * @param retry whether it is a retry of an already attempted message or not.
+   * @param pdu PDUs representing the contents of the message.
+   */
+  public void sendSms(int format, int messageRef, boolean isRetry, byte[] pdu) {
+  }
+
+  /**
+   * This method will be triggered by the platform after {@link #deliverSms(int, byte[])} has been
+   * called to deliver the result to the IMS provider. It will also be triggered after
+   * {@link #setSentSmsResult(int, int)} has been called to provide the result of the operation.
+   *
+   * @param result Should be {@link #DELIVER_STATUS_OK} if the message was delivered successfully,
+   * {@link #DELIVER_STATUS_ERROR} otherwise.
+   * @param messageRef the message reference.
+   */
+  public void acknowledgeSms(int messageRef, int result) {
+
+  }
+
+  /**
+   * This method should be triggered by the IMS providers when there is an incoming message. The
+   * platform will deliver the message to the messages database and notify the IMS provider of the
+   * result by calling {@link #acknowledgeSms(int)}.
+   *
+   * This method must not be called before {@link #onFeatureReady()} is called.
+   *
+   * @param format the format of the message.One of {@link #IMS_SMS_FORMAT_3GPP} or
+   *                {@link #IMS_SMS_FORMAT_3GPP2}
+   * @param pdu PDUs representing the contents of the message.
+   * @throws IllegalStateException if called before {@link #onFeatureReady()}
+   */
+  public final void deliverSms(int format, byte[] pdu) throws IllegalStateException {
+    // TODO: Guard against NPE/ Check if feature is ready and thrown an exception
+    // otherwise.
+    try {
+      mSmsListener.deliverSms(format, pdu);
+    } catch (RemoteException e) {
+    }
+  }
+
+  /**
+   * This method should be triggered by the IMS providers to pass the result of the sent message
+   * to the platform.
+   *
+   * This method must not be called before {@link #onFeatureReady()} is called.
+   *
+   * @param messageRef the message reference.
+   * @param result One of {@link #SEND_STATUS_OK}, {@link #SEND_STATUS_ERROR},
+   *                {@link #SEND_STATUS_ERROR_RETRY}, {@link #SEND_STATUS_ERROR_FALLBACK}
+   * @throws IllegalStateException if called before {@link #onFeatureReady()}
+   */
+  public final void setSentSmsResult(int messageRef, int result) throws IllegalStateException {
+    // TODO: Guard against NPE/ Check if feature is ready and thrown an exception
+    // otherwise.
+    try {
+      mSmsListener.setSentSmsResult(messageRef, result);
+    } catch (RemoteException e) {
+    }
+  }
+
+  /**
+   * Sets the status report of the sent message.
+   *
+   * @param format Should be {@link #IMS_SMS_FORMAT_3GPP} or {@link #IMS_SMS_FORMAT_3GPP2}
+   * @param pdu PDUs representing the content of the status report.
+   * @throws IllegalStateException if called before {@link #onFeatureReady()}
+   */
+  public final void setSentSmsStatusReport(int format, byte[] pdu) {
+    // TODO: Guard against NPE/ Check if feature is ready and thrown an exception
+    // otherwise.
+    try {
+      mSmsListener.setSentSmsStatusReport(format, pdu);
+    } catch (RemoteException e) {
+    }
+  }
+
+  /**
+   * Returns the SMS format. Default is {@link #IMS_SMS_FORMAT_3GPP} unless overridden by IMS
+   * Provider.
+   *
+   * @return sms format.
+   */
+  public int getSmsFormat() {
+    return IMS_SMS_FORMAT_3GPP;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void onFeatureReady() {
+
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void onFeatureRemoved() {
+
+  }
+
+  /**
+   * @hide
+   */
+  @Override
+  public final IImsSmsFeature getBinder() {
+    return mIImsSmsBinder;
+  }
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/ims/internal/IImsSmsFeature.aidl b/telephony/java/com/android/ims/internal/IImsSmsFeature.aidl
new file mode 100644
index 0000000..5068128
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsSmsFeature.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 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.ims.internal;
+
+import com.android.ims.internal.ISmsListener;
+
+/**
+ * See SmsFeature for more information.
+ *
+ * {@hide}
+ */
+interface IImsSmsFeature {
+    void registerSmsListener(in ISmsListener listener);
+    void sendSms(in int format, in int messageRef, in boolean retry, in byte[] pdu);
+    void acknowledgeSms(in int messageRef, in int result);
+    int getSmsFormat();
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/ims/internal/ISmsListener.aidl b/telephony/java/com/android/ims/internal/ISmsListener.aidl
new file mode 100644
index 0000000..1266f04
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/ISmsListener.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 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.ims.internal;
+
+/**
+ * See SmsFeature for more information.
+ * {@hide}
+ */
+interface ISmsListener {
+    void setSentSmsResult(in int messageRef, in int result);
+    void setSentSmsStatusReport(in int format, in byte[] pdu);
+    void deliverSms(in int format, in byte[] pdu);
+}
\ No newline at end of file
diff --git a/test-base/Android.mk b/test-base/Android.mk
index 9fc70f3..6a1ac9e 100644
--- a/test-base/Android.mk
+++ b/test-base/Android.mk
@@ -46,20 +46,6 @@
 
 include $(BUILD_JAVA_LIBRARY)
 
-# Build the repackaged-legacy-test library
-# ========================================
-# This contains repackaged versions of the classes from legacy-test.
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := repackaged-legacy-test
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-LOCAL_JARJAR_RULES := $(LOCAL_PATH)/jarjar-rules.txt
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
 # Build the repackaged.android.test.base library
 # ==============================================
 # This contains repackaged versions of the classes from legacy-test.
diff --git a/test-mock/Android.mk b/test-mock/Android.mk
index e4af17c..2c07955 100644
--- a/test-mock/Android.mk
+++ b/test-mock/Android.mk
@@ -24,7 +24,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework legacy-test
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
 
 LOCAL_JARJAR_RULES := $(LOCAL_PATH)/../test-base/jarjar-rules.txt