Merge "Merge "Reduce excess local prefix computations" am: 35d9291ca7 am: 069fd8e996 am: 7b86429051"
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 4bbcfd5..febb922 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -267,10 +267,12 @@
     }
 }
 
-LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) {
+LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) : LogEvent(tagId, timestampNs, 0) {}
+
+LogEvent::LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid) {
     mLogdTimestampNs = timestampNs;
     mTagId = tagId;
-    mLogUid = 0;
+    mLogUid = uid;
     mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
     if (mContext) {
         android_log_write_int64(mContext, timestampNs);
@@ -344,7 +346,8 @@
     return false;
 }
 
-bool LogEvent::writeKeyValuePairs(const std::map<int32_t, int32_t>& int_map,
+bool LogEvent::writeKeyValuePairs(int32_t uid,
+                                  const std::map<int32_t, int32_t>& int_map,
                                   const std::map<int32_t, int64_t>& long_map,
                                   const std::map<int32_t, std::string>& string_map,
                                   const std::map<int32_t, float>& float_map) {
@@ -352,6 +355,7 @@
          if (android_log_write_list_begin(mContext) < 0) {
             return false;
          }
+         write(uid);
          for (const auto& itr : int_map) {
              if (android_log_write_list_begin(mContext) < 0) {
                 return false;
@@ -561,6 +565,10 @@
         }
         i++;
     } while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
+    if (isKeyValuePairAtom && mValues.size() > 0) {
+        mValues[0] = FieldValue(Field(android::util::KEY_VALUE_PAIRS_ATOM, getSimpleField(1)),
+                                Value((int32_t)mLogUid));
+    }
 }
 
 int64_t LogEvent::GetLong(size_t key, status_t* err) const {
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index c7e2a8c..3d5b2ab 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -75,6 +75,9 @@
     // For testing. The timestamp is used as both elapsed real time and logd timestamp.
     explicit LogEvent(int32_t tagId, int64_t timestampNs);
 
+    // For testing. The timestamp is used as both elapsed real time and logd timestamp.
+    explicit LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid);
+
     /**
      * Constructs a KeyValuePairsAtom LogEvent from value maps.
      */
@@ -147,7 +150,8 @@
     bool write(float value);
     bool write(const std::vector<AttributionNodeInternal>& nodes);
     bool write(const AttributionNodeInternal& node);
-    bool writeKeyValuePairs(const std::map<int32_t, int32_t>& int_map,
+    bool writeKeyValuePairs(int32_t uid,
+                            const std::map<int32_t, int32_t>& int_map,
                             const std::map<int32_t, int64_t>& long_map,
                             const std::map<int32_t, std::string>& string_map,
                             const std::map<int32_t, float>& float_map);
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index ced65f2..f59ac1a 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -90,7 +90,7 @@
 }
 
 TEST(LogEventTest, TestKeyValuePairsAtomParsing) {
-    LogEvent event1(83, 2000);
+    LogEvent event1(83, 2000, 1000);
     std::map<int32_t, int32_t> int_map;
     std::map<int32_t, int64_t> long_map;
     std::map<int32_t, std::string> string_map;
@@ -108,7 +108,8 @@
     float_map[111] = 2.2f;
     float_map[222] = 1.1f;
 
-    EXPECT_TRUE(event1.writeKeyValuePairs(int_map,
+    EXPECT_TRUE(event1.writeKeyValuePairs(0, // Logging side logs 0 uid.
+                                          int_map,
                                           long_map,
                                           string_map,
                                           float_map));
@@ -116,87 +117,92 @@
 
     EXPECT_EQ(83, event1.GetTagId());
     const auto& items = event1.getValues();
-    EXPECT_EQ((size_t)16, items.size());
+    EXPECT_EQ((size_t)17, items.size());
 
     const FieldValue& item0 = event1.getValues()[0];
-    EXPECT_EQ(0x2010101, item0.mField.getField());
+    EXPECT_EQ(0x10000, item0.mField.getField());
     EXPECT_EQ(Type::INT, item0.mValue.getType());
-    EXPECT_EQ(11, item0.mValue.int_value);
+    EXPECT_EQ(1000, item0.mValue.int_value);
 
     const FieldValue& item1 = event1.getValues()[1];
-    EXPECT_EQ(0x2010182, item1.mField.getField());
+    EXPECT_EQ(0x2010201, item1.mField.getField());
     EXPECT_EQ(Type::INT, item1.mValue.getType());
-    EXPECT_EQ(123, item1.mValue.int_value);
+    EXPECT_EQ(11, item1.mValue.int_value);
 
     const FieldValue& item2 = event1.getValues()[2];
-    EXPECT_EQ(0x2010201, item2.mField.getField());
+    EXPECT_EQ(0x2010282, item2.mField.getField());
     EXPECT_EQ(Type::INT, item2.mValue.getType());
-    EXPECT_EQ(22, item2.mValue.int_value);
+    EXPECT_EQ(123, item2.mValue.int_value);
 
     const FieldValue& item3 = event1.getValues()[3];
-    EXPECT_EQ(0x2010282, item3.mField.getField());
+    EXPECT_EQ(0x2010301, item3.mField.getField());
     EXPECT_EQ(Type::INT, item3.mValue.getType());
-    EXPECT_EQ(345, item3.mValue.int_value);
+    EXPECT_EQ(22, item3.mValue.int_value);
 
     const FieldValue& item4 = event1.getValues()[4];
-    EXPECT_EQ(0x2010301, item4.mField.getField());
+    EXPECT_EQ(0x2010382, item4.mField.getField());
     EXPECT_EQ(Type::INT, item4.mValue.getType());
-    EXPECT_EQ(33, item4.mValue.int_value);
+    EXPECT_EQ(345, item4.mValue.int_value);
 
     const FieldValue& item5 = event1.getValues()[5];
-    EXPECT_EQ(0x2010382, item5.mField.getField());
-    EXPECT_EQ(Type::LONG, item5.mValue.getType());
-    EXPECT_EQ(678L, item5.mValue.int_value);
+    EXPECT_EQ(0x2010401, item5.mField.getField());
+    EXPECT_EQ(Type::INT, item5.mValue.getType());
+    EXPECT_EQ(33, item5.mValue.int_value);
 
     const FieldValue& item6 = event1.getValues()[6];
-    EXPECT_EQ(0x2010401, item6.mField.getField());
-    EXPECT_EQ(Type::INT, item6.mValue.getType());
-    EXPECT_EQ(44, item6.mValue.int_value);
+    EXPECT_EQ(0x2010482, item6.mField.getField());
+    EXPECT_EQ(Type::LONG, item6.mValue.getType());
+    EXPECT_EQ(678L, item6.mValue.int_value);
 
     const FieldValue& item7 = event1.getValues()[7];
-    EXPECT_EQ(0x2010482, item7.mField.getField());
-    EXPECT_EQ(Type::LONG, item7.mValue.getType());
-    EXPECT_EQ(890L, item7.mValue.int_value);
+    EXPECT_EQ(0x2010501, item7.mField.getField());
+    EXPECT_EQ(Type::INT, item7.mValue.getType());
+    EXPECT_EQ(44, item7.mValue.int_value);
 
     const FieldValue& item8 = event1.getValues()[8];
-    EXPECT_EQ(0x2010501, item8.mField.getField());
-    EXPECT_EQ(Type::INT, item8.mValue.getType());
-    EXPECT_EQ(1, item8.mValue.int_value);
+    EXPECT_EQ(0x2010582, item8.mField.getField());
+    EXPECT_EQ(Type::LONG, item8.mValue.getType());
+    EXPECT_EQ(890L, item8.mValue.int_value);
 
     const FieldValue& item9 = event1.getValues()[9];
-    EXPECT_EQ(0x2010583, item9.mField.getField());
-    EXPECT_EQ(Type::STRING, item9.mValue.getType());
-    EXPECT_EQ("test2", item9.mValue.str_value);
+    EXPECT_EQ(0x2010601, item9.mField.getField());
+    EXPECT_EQ(Type::INT, item9.mValue.getType());
+    EXPECT_EQ(1, item9.mValue.int_value);
 
     const FieldValue& item10 = event1.getValues()[10];
-    EXPECT_EQ(0x2010601, item10.mField.getField());
-    EXPECT_EQ(Type::INT, item10.mValue.getType());
-    EXPECT_EQ(2, item10.mValue.int_value);
+    EXPECT_EQ(0x2010683, item10.mField.getField());
+    EXPECT_EQ(Type::STRING, item10.mValue.getType());
+    EXPECT_EQ("test2", item10.mValue.str_value);
 
     const FieldValue& item11 = event1.getValues()[11];
-    EXPECT_EQ(0x2010683, item11.mField.getField());
-    EXPECT_EQ(Type::STRING, item11.mValue.getType());
-    EXPECT_EQ("test1", item11.mValue.str_value);
+    EXPECT_EQ(0x2010701, item11.mField.getField());
+    EXPECT_EQ(Type::INT, item11.mValue.getType());
+    EXPECT_EQ(2, item11.mValue.int_value);
 
     const FieldValue& item12 = event1.getValues()[12];
-    EXPECT_EQ(0x2010701, item12.mField.getField());
-    EXPECT_EQ(Type::INT, item12.mValue.getType());
-    EXPECT_EQ(111, item12.mValue.int_value);
+    EXPECT_EQ(0x2010783, item12.mField.getField());
+    EXPECT_EQ(Type::STRING, item12.mValue.getType());
+    EXPECT_EQ("test1", item12.mValue.str_value);
 
     const FieldValue& item13 = event1.getValues()[13];
-    EXPECT_EQ(0x2010784, item13.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item13.mValue.getType());
-    EXPECT_EQ(2.2f, item13.mValue.float_value);
+    EXPECT_EQ(0x2010801, item13.mField.getField());
+    EXPECT_EQ(Type::INT, item13.mValue.getType());
+    EXPECT_EQ(111, item13.mValue.int_value);
 
     const FieldValue& item14 = event1.getValues()[14];
-    EXPECT_EQ(0x2018801, item14.mField.getField());
-    EXPECT_EQ(Type::INT, item14.mValue.getType());
-    EXPECT_EQ(222, item14.mValue.int_value);
+    EXPECT_EQ(0x2010884, item14.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item14.mValue.getType());
+    EXPECT_EQ(2.2f, item14.mValue.float_value);
 
     const FieldValue& item15 = event1.getValues()[15];
-    EXPECT_EQ(0x2018884, item15.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item15.mValue.getType());
-    EXPECT_EQ(1.1f, item15.mValue.float_value);
+    EXPECT_EQ(0x2018901, item15.mField.getField());
+    EXPECT_EQ(Type::INT, item15.mValue.getType());
+    EXPECT_EQ(222, item15.mValue.int_value);
+
+    const FieldValue& item16 = event1.getValues()[16];
+    EXPECT_EQ(0x2018984, item16.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item16.mValue.getType());
+    EXPECT_EQ(1.1f, item16.mValue.float_value);
 }
 
 TEST(LogEventTest, TestLogParsing2) {
@@ -292,6 +298,7 @@
     EXPECT_EQ(83, event1.GetTagId());
     EXPECT_EQ((int64_t)2000, event1.GetLogdTimestampNs());
     EXPECT_EQ((int64_t)2001, event1.GetElapsedTimestampNs());
+    EXPECT_EQ((int64_t)10001, event1.GetUid());
 
     const auto& items = event1.getValues();
     EXPECT_EQ((size_t)17, items.size());
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index e9acdc3..d24b822 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -30,6 +30,7 @@
 import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.inputmethodservice.InputMethodService;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -753,10 +754,20 @@
             throw new IllegalStateException(e);
         }
         final InputMethodManager imm = new InputMethodManager(service, displayId, looper);
+        // InputMethodManagerService#addClient() relies on Binder.getCalling{Pid, Uid}() to
+        // associate PID/UID with each IME client. This means:
+        //  A. if this method call will be handled as an IPC, there is no problem.
+        //  B. if this method call will be handled as an in-proc method call, we need to
+        //     ensure that Binder.getCalling{Pid, Uid}() return Process.my{Pid, Uid}()
+        // Either ways we can always call Binder.{clear, restore}CallingIdentity() because
+        // 1) doing so has no effect for A and 2) doing so is sufficient for B.
+        final long identity = Binder.clearCallingIdentity();
         try {
             service.addClient(imm.mClient, imm.mIInputContext, displayId);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
         return imm;
     }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 374c7ea..176fedb 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -400,6 +400,7 @@
 
     <protected-broadcast android:name="android.telecom.action.DEFAULT_DIALER_CHANGED" />
     <protected-broadcast android:name="android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED" />
+    <protected-broadcast android:name="android.provider.action.SMS_MMS_DB_CREATED" />
     <protected-broadcast android:name="android.intent.action.CONTENT_CHANGED" />
     <protected-broadcast android:name="android.provider.Telephony.MMS_DOWNLOADED" />
 
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 097ce44..ba483fb 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -47,6 +47,20 @@
     <dimen name="navigation_bar_height_landscape">48dp</dimen>
     <!-- Width of the navigation bar when it is placed vertically on the screen -->
     <dimen name="navigation_bar_width">48dp</dimen>
+
+    <!-- EXPERIMENT BEGIN -->
+    <!-- Height of the bottom navigation bar frame; this is different than navigation_bar_height
+         where that is the height reported to all the other windows to resize themselves around the
+         navigation bar window but navigation_bar_frame_height is reported to SystemUI navigation
+         bar view's window -->
+    <dimen name="navigation_bar_frame_height">@dimen/navigation_bar_height</dimen>
+    <!-- Width of the left/right navigation bar frame; this is different than navigation_bar_width
+         where that is the width reported to all the other windows to resize themselves around the
+         navigation bar window but navigation_bar_frame_width is reported to SystemUI navigation
+         bar view's window -->
+    <dimen name="navigation_bar_frame_width">@dimen/navigation_bar_width</dimen>
+    <!-- EXPERIMENT END-->
+
     <!-- Height of the bottom navigation / system bar in car mode. -->
     <dimen name="navigation_bar_height_car_mode">96dp</dimen>
     <!-- Height of the bottom navigation bar in portrait; often the same as
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 81a1bf8..0e787cd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1681,6 +1681,8 @@
   <java-symbol type="dimen" name="navigation_bar_height" />
   <java-symbol type="dimen" name="navigation_bar_height_landscape" />
   <java-symbol type="dimen" name="navigation_bar_width" />
+  <java-symbol type="dimen" name="navigation_bar_frame_height" />
+  <java-symbol type="dimen" name="navigation_bar_frame_width" />
   <java-symbol type="dimen" name="navigation_bar_height_car_mode" />
   <java-symbol type="dimen" name="navigation_bar_height_landscape_car_mode" />
   <java-symbol type="dimen" name="navigation_bar_width_car_mode" />
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/Android.mk b/packages/overlays/ExperimentNavigationBarFloatingOverlay/Android.mk
new file mode 100644
index 0000000..ee2ddc8
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/Android.mk
@@ -0,0 +1,30 @@
+#
+#  Copyright 2018, 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := ExperimentNavigationBarFloating
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := ExperimentNavigationBarFloatingOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/AndroidManifest.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..b4b2b16
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<!--
+/**
+ * Copyright (c) 2018, 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.internal.experiment.navbar.floating"
+        android:versionCode="1"
+        android:versionName="1.0">
+    <overlay android:targetPackage="android"
+        android:category="com.android.internal.experiment_navbar_floating"
+        android:priority="1"/>
+
+    <application android:label="@string/experiment_navigationbar_overlay" android:hasCode="false"/>
+</manifest>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/config.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/config.xml
new file mode 100644
index 0000000..6a58453
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, 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.
+ */
+-->
+<resources>
+    <!-- Height of the bottom navigation / system bar. -->
+    <dimen name="navigation_bar_height">0dp</dimen>
+    <!-- Width of the navigation bar when it is placed vertically on the screen -->
+    <dimen name="navigation_bar_width">0dp</dimen>
+    <!-- Height of the bottom navigation / system bar frame; navigation buttons height. -->
+    <dimen name="navigation_bar_frame_height">48dp</dimen>
+    <!-- Width of the navigation bar frame when it is placed vertically on the screen -->
+    <dimen name="navigation_bar_frame_width">48dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/strings.xml
new file mode 100644
index 0000000..884846d
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Name of overlay [CHAR LIMIT=64] -->
+    <string name="experiment_navigationbar_overlay">Floating Navigation Bar Experiment</string>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/Android.mk b/packages/overlays/ExperimentNavigationBarSlimOverlay/Android.mk
new file mode 100644
index 0000000..e642a68
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/Android.mk
@@ -0,0 +1,30 @@
+#
+#  Copyright 2018, 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := ExperimentNavigationBarSlim
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := ExperimentNavigationBarSlimOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/AndroidManifest.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..a1bd582
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<!--
+/**
+ * Copyright (c) 2018, 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.internal.experiment.navbar.slim"
+        android:versionCode="1"
+        android:versionName="1.0">
+    <overlay android:targetPackage="android"
+        android:category="com.android.internal.experiment_navbar_slim"
+        android:priority="1"/>
+
+    <application android:label="@string/experiment_navigationbar_overlay" android:hasCode="false"/>
+</manifest>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/config.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/config.xml
new file mode 100644
index 0000000..4c3571a
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, 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.
+ */
+-->
+<resources>
+    <!-- Height of the bottom navigation / system bar. -->
+    <dimen name="navigation_bar_height">36dp</dimen>
+    <!-- Width of the navigation bar when it is placed vertically on the screen -->
+    <dimen name="navigation_bar_width">36dp</dimen>
+    <!-- Height of the bottom navigation / system bar frame; navigation buttons height. -->
+    <dimen name="navigation_bar_frame_width">36dp</dimen>
+    <!-- Width of the navigation bar frame when it is placed vertically on the screen -->
+    <dimen name="navigation_bar_frame_height">36dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/strings.xml
new file mode 100644
index 0000000..5ca9d15
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Name of overlay [CHAR LIMIT=64] -->
+    <string name="experiment_navigationbar_overlay">Slim Navigation Bar Experiment</string>
+</resources>
\ No newline at end of file
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index e37153e..e3a1a91 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1770,6 +1770,12 @@
     @Override
     public void addClient(IInputMethodClient client, IInputContext inputContext,
             int selfReportedDisplayId) {
+        // Here there are two scenarios where this method is called:
+        // A. IMM is being instantiated in a different process and this is an IPC from that process
+        // B. IMM is being instantiated in the same process but Binder.clearCallingIdentity() is
+        //    called in the caller side if necessary.
+        // In either case the following UID/PID should be the ones where InputMethodManager is
+        // actually running.
         final int callerUid = Binder.getCallingUid();
         final int callerPid = Binder.getCallingPid();
         synchronized (mMethodMap) {
@@ -1778,7 +1784,7 @@
                 if (state.uid == callerUid && state.pid == callerPid
                         && state.selfReportedDisplayId == selfReportedDisplayId) {
                     throw new SecurityException("uid=" + callerUid + "/pid=" + callerPid
-                            + " is already registered");
+                            + "/displayId=" + selfReportedDisplayId + " is already registered.");
                 }
             }
             final ClientDeathRecipient deathRecipient = new ClientDeathRecipient(this, client);
diff --git a/services/core/java/com/android/server/policy/NavigationBarExperiments.java b/services/core/java/com/android/server/policy/NavigationBarExperiments.java
new file mode 100644
index 0000000..06772e3
--- /dev/null
+++ b/services/core/java/com/android/server/policy/NavigationBarExperiments.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2018 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.policy;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
+
+import android.content.Context;
+import android.graphics.Rect;
+
+import com.android.server.policy.WindowManagerPolicy.WindowState;
+import com.android.server.wm.WindowFrames;
+
+/**
+ * This class acts as a proxy for Navigation Bar experiments enabled with custom overlays
+ * {@see OverlayManagerService}. By default with no overlays, this class will essentially do nothing
+ * and pass the original resource data back. By default the navigation bar height/width is the same
+ * as the frame height/width and therefore any offsets calculated will cancel out and do nothing.
+ * TODO(b/113952590): Remove class once experiment in bug is completed
+ */
+public class NavigationBarExperiments {
+
+    private int mNavigationBarHeight;
+    private int mNavigationBarWidth;
+
+    /**
+     * This represents the height of the navigation bar buttons. With no experiments or overlays
+     * enabled, the frame height is the same as the normal navigation bar height.
+     */
+    private int mNavigationBarFrameHeight;
+
+    /**
+     * This represents the width of the navigation bar buttons. With no experiments or overlays
+     * enabled, the frame width is the same as the normal navigation bar width.
+     */
+    private int mNavigationBarFrameWidth;
+
+    /**
+     * Call when configuration change to refresh resource dimensions
+     * @param systemUiContext to get the resource values
+     */
+    public void onConfigurationChanged(Context systemUiContext) {
+        // Cache all the values again
+        mNavigationBarHeight = systemUiContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_height);
+        mNavigationBarWidth = systemUiContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_width);
+        mNavigationBarFrameHeight = systemUiContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_frame_height);
+        mNavigationBarFrameWidth = systemUiContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_frame_width);
+    }
+
+    public int getNavigationBarHeight() {
+        return mNavigationBarHeight;
+    }
+
+    public int getNavigationBarWidth() {
+        return mNavigationBarWidth;
+    }
+
+    public int getNavigationBarFrameHeight() {
+        return mNavigationBarFrameHeight;
+    }
+
+    public int getNavigationBarFrameWidth() {
+        return mNavigationBarFrameWidth;
+    }
+
+    /**
+     * If navigation frame width/height is different than navigation bar width/height then only
+     * offset the ime's and home activity's window rects depending on the navigation bar position to
+     * add a gap where the navigation bar would have been drawn. With no experiments or overlays
+     * enabled, the height/width is the same as the frame height/width and the offsets calculated
+     * will be 0 and this function will do nothing.
+     * @param navPosition position of navigation bar (left, right or bottom)
+     * @param w the window that is being offset by experiment
+     */
+    public void offsetWindowFramesForNavBar(int navPosition, WindowState w) {
+        if (w.getAttrs().type != TYPE_INPUT_METHOD && w.getActivityType() != ACTIVITY_TYPE_HOME) {
+            return;
+        }
+
+        final WindowFrames windowFrames = w.getWindowFrames();
+        final Rect cf = windowFrames.mContentFrame;
+        switch (navPosition) {
+            case NAV_BAR_BOTTOM:
+                int navHeight = getNavigationBarFrameHeight() - getNavigationBarHeight();
+                if (navHeight > 0) {
+                    cf.bottom -= navHeight;
+                }
+                break;
+            case NAV_BAR_LEFT:
+            case NAV_BAR_RIGHT:
+                int navWidth = getNavigationBarFrameWidth() - getNavigationBarWidth();
+                if (navWidth > 0) {
+                    if (navPosition == NAV_BAR_LEFT) {
+                        cf.left += navWidth;
+                    } else {
+                        cf.right -= navWidth;
+                    }
+                }
+                break;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c5cee32..371ac4f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -779,6 +779,10 @@
 
     private boolean mAodShowing;
 
+    // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+    private NavigationBarExperiments mExperiments = new NavigationBarExperiments();
+    // EXPERIMENT END
+
     private static final int MSG_ENABLE_POINTER_LOCATION = 1;
     private static final int MSG_DISABLE_POINTER_LOCATION = 2;
     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
@@ -2607,6 +2611,10 @@
                     res.getDimensionPixelSize(
                             com.android.internal.R.dimen.navigation_bar_width_car_mode);
         }
+
+        // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+        mExperiments.onConfigurationChanged(uiContext);
+        // EXPERIMENT END
     }
 
     @VisibleForTesting
@@ -4534,7 +4542,11 @@
             // It's a system nav bar or a portrait screen; nav bar goes on bottom.
             final int top = cutoutSafeUnrestricted.bottom
                     - getNavigationBarHeight(rotation, uiMode);
-            navigationFrame.set(0, top, displayWidth, displayFrames.mUnrestricted.bottom);
+            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+            final int topNavBar = cutoutSafeUnrestricted.bottom
+                    - mExperiments.getNavigationBarFrameHeight();
+            navigationFrame.set(0, topNavBar, displayWidth, displayFrames.mUnrestricted.bottom);
+            // EXPERIMENT END
             displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -4557,7 +4569,11 @@
             // Landscape screen; nav bar goes to the right.
             final int left = cutoutSafeUnrestricted.right
                     - getNavigationBarWidth(rotation, uiMode);
-            navigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
+            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+            final int leftNavBar = cutoutSafeUnrestricted.right
+                    - mExperiments.getNavigationBarFrameWidth();
+            navigationFrame.set(leftNavBar, 0, displayFrames.mUnrestricted.right, displayHeight);
+            // EXPERIMENT END
             displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -4580,7 +4596,11 @@
             // Seascape screen; nav bar goes to the left.
             final int right = cutoutSafeUnrestricted.left
                     + getNavigationBarWidth(rotation, uiMode);
-            navigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
+            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+            final int rightNavBar = cutoutSafeUnrestricted.left
+                    + mExperiments.getNavigationBarFrameWidth();
+            navigationFrame.set(displayFrames.mUnrestricted.left, 0, rightNavBar, displayHeight);
+            // EXPERIMENT END
             displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -4790,6 +4810,12 @@
                     pf.left = df.left = of.left = cf.left = vf.left = displayFrames.mStable.left;
                 }
             }
+
+            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+            // Offset the ime to avoid overlapping with the nav bar
+            mExperiments.offsetWindowFramesForNavBar(mNavigationBarPosition, win);
+            // EXPERIMENT END
+
             // IM dock windows always go to the bottom of the screen.
             attrs.gravity = Gravity.BOTTOM;
             mDockLayer = win.getSurfaceLayer();
@@ -4930,6 +4956,10 @@
                     } else {
                         vf.set(cf);
                     }
+
+                    // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+                    mExperiments.offsetWindowFramesForNavBar(mNavigationBarPosition, win);
+                    // EXPERIMENT END
                 }
             } else if (layoutInScreen || (sysUiFl
                     & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index db13cbc..e1c4acf 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -66,6 +66,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.WindowConfiguration;
 import android.content.Context;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
@@ -437,6 +438,14 @@
         int getWindowingMode();
 
         /**
+         * Returns the {@link WindowConfiguration.ActivityType} associated with the configuration
+         * of this window.
+         */
+        default int getActivityType() {
+            return WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+        }
+
+        /**
          * Returns true if the window is current in multi-windowing mode. i.e. it shares the
          * screen with other application windows.
          */
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index d9e7167..6c9c01c 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -1245,6 +1245,33 @@
                     "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL";
 
             /**
+             * Broadcast action: When SMS-MMS db is being created. If file-based encryption is
+             * supported, this broadcast indicates creation of the db in credential-encrypted
+             * storage. A boolean is specified in {@link #EXTRA_IS_INITIAL_CREATE} to indicate if
+             * this is the initial create of the db. Requires
+             * {@link android.Manifest.permission#READ_SMS} to receive.
+             *
+             * @see #EXTRA_IS_INITIAL_CREATE
+             *
+             * @hide
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String ACTION_SMS_MMS_DB_CREATED =
+                    "android.provider.action.SMS_MMS_DB_CREATED";
+
+            /**
+             * Boolean flag passed as an extra with {@link #ACTION_SMS_MMS_DB_CREATED} to indicate
+             * whether the DB creation is the initial creation on the device, that is it is after a
+             * factory-data reset or a new device. Any subsequent creations of the DB (which
+             * happens only in error scenarios) will have this flag set to false.
+             *
+             * @see #ACTION_SMS_MMS_DB_CREATED
+             *
+             * @hide
+             */
+            public static final String EXTRA_IS_INITIAL_CREATE =
+                    "android.provider.extra.IS_INITIAL_CREATE";
+            /**
              * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
              * {@link #DATA_SMS_RECEIVED_ACTION} intent.
              *